home *** CD-ROM | disk | FTP | other *** search
/ IRIS Performer 2.2 Friends Demo / SGI IRIS Performer 2.2 Friends Demo.iso / friends / coryphaeus / dwb_loader / pfdwb.c next >
C/C++ Source or Header  |  1997-10-31  |  133KB  |  4,667 lines

  1. /*
  2.  * Copyright (C) Coryphaeus Software, Inc. 1994
  3.  *
  4.  *   DWB Loader for Performer 2.0
  5.  *
  6.  */
  7.  
  8.   static char revision[] = "$Revision: 1.10 $";
  9.   static char date[] = "$Date: 1995/07/31 20:06:39 $";
  10.   static char source[] = "$RCSfile: pfdwb.c,v $";
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <bstring.h>
  16. #include <ctype.h>
  17. #include <malloc.h>
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <math.h>
  21.  
  22. #ifdef IRISGL
  23. #define Cursor iglCursor
  24. #include <gl/gl.h>
  25. #undef Cursor
  26. #else
  27. #include <GL/gl.h>
  28. #endif /* end GL type */
  29.  
  30. #include <Performer/pf.h>
  31. #include <Performer/pr.h>
  32. #include <Performer/pfdu.h>
  33.  
  34. #include "pfdwb.h"    
  35.  
  36.  
  37. /*========================================================================
  38.  *========================================================================
  39.  *
  40.  *                      Defines and Macros
  41.  *
  42.  *========================================================================
  43.  *========================================================================*/
  44.  
  45. #define LOWEST_DWB_FORMAT_VERSION_SUPPORTED    2.1
  46. #define HIGHEST_DWB_FORMAT_VERSION_SUPPORTED    3.0
  47. #define FLUSH_AND_EXIT     { fflush (stderr); exit (-1); } 
  48. #define ROUNDING_ERROR                0.05
  49.  
  50. /* string comparison that avoids function call when possible */
  51. #define SAME(_a, _b)    (strcasecmp(_a, _b) == 0)
  52.  
  53. /* define program limits and sizes */
  54. #define    BUFFER_SIZE    4096
  55. #define    MAX_STRING    4096
  56. #define    GFX_REALITY    0x1
  57. #define    GFX_MULTISAMPLE    0x10
  58.  
  59. /* define parse render group instructions */
  60. #define GET_ALL_POLYS    0
  61. #define GET_ONE_POLY    1
  62.  
  63. #define NORMAL        0
  64. #define LAYER_BASE    2
  65. #define LAYER_DECAL    4
  66. #define DECAL_NONE     -1
  67. #define LIGHTPOINT    8
  68. #define BILLBOARD    16
  69. #define SEQUENCE    32
  70.  
  71. #define RADTODEG 57.29578
  72. #define DEGTORAD 0.017453293
  73. #define copyNyup(dst,src,m) \
  74.        {dst[0]=  src[0] * m; dst[1]= src[1] * m; dst[2]= src[2] * m; }
  75.  
  76. /*----------------------------------------------*/
  77. /* Macro to set the builder utility color array */
  78. /*----------------------------------------------*/
  79.  
  80. #define SET_COLOR(poly,i,color_index,packed_color)        \
  81. {                                \
  82.     float tmp_arr[4]; int tmp_int;                \
  83.     if ( color_index == PACKED_COLOR_INDEX )            \
  84.     {                                \
  85.         unPackRGBA ( packed_color,tmp_arr );            \
  86.         for ( tmp_int=0; tmp_int<3; tmp_int++ )            \
  87.             poly->colors[i][tmp_int] = tmp_arr[tmp_int];     \
  88.     }                                \
  89.     else                            \
  90.     pfCopyVec3 ( poly->colors[i],dwbRoot->colorTable[color_index] );\
  91.     poly->colors[i][3] = dwbRoot->currentGroup.alpha;        \
  92. }
  93.  
  94.  
  95.  
  96. /*========================================================================
  97.  *========================================================================
  98.  *
  99.  *                      PRIVATE variables
  100.  *
  101.  *========================================================================
  102.  *========================================================================*/
  103. /* 
  104.  * The DRT loader package uses checkForLink otherwise just throw away any
  105.  * unknown opcodes.
  106.  */
  107.  
  108. #ifndef LINKLOADER
  109.  
  110. static int checkForLink( memPtr *ifp, short opcode, short length, 
  111.                   pfNode *parent, pfNode **current, int treeDepth )
  112. {
  113.  
  114.   /* comment this out if you do not want info on unknowns */ 
  115. /*  printf("\t\tUnknown opcode %u \t: length %u \n",opcode,length); */
  116.  
  117.   /* throw away everything */
  118.   memSeek(ifp,length,SEEK_CUR);
  119. }
  120.  
  121. #else
  122.  
  123. extern int checkForLink( memPtr *ifp, short opcode, short length, 
  124.                          pfNode *parent, pfNode **current, int depth );
  125.  
  126. #endif
  127.  
  128.  
  129. typedef struct _LineStyle
  130. {
  131.     short index;
  132.     short style;
  133.  
  134. } LineStyle;
  135.  
  136.  
  137. /*---------------------------------------------------------------------------*/
  138. /*                             Global structures                             */
  139. /*---------------------------------------------------------------------------*/
  140. static short faceBackColor;
  141. static int externDepth =0;
  142. #define MAX_EXTERN_DEPTH 100
  143. static dwbFile *externArray[MAX_EXTERN_DEPTH];
  144. static int externChildYUp[MAX_EXTERN_DEPTH+1];
  145. static LineStyle *lineStyles;          /* local linestyle pallete */
  146.  
  147. /*---------------------------------------------------------------------------*/
  148. /*                               Global Variables                            */
  149. /*---------------------------------------------------------------------------*/
  150.        void             *Arena;             /*Performer shared memory Arena*/
  151. static int               GfxType;
  152.        dwbFile        *dwbRoot;        /*local container for global vars */
  153. static pfTexEnv         *defTEnv = NULL;    /*default texture environment */
  154. static pfSphere groupBoundingSphere;
  155. static int      currentFacePType = -1; /* current polygon type of the face */
  156.  
  157. static int      extendedVersion = 0;   /* version 2.28 and above */
  158.  
  159. static int clipMode =  CLIP_INITIAL;  /* by default only calculate a clip
  160.                      region once */
  161.  
  162. pfNode *LODChild = NULL; /* set by pfdwb.c used by drt.c */
  163. pfNode *LODParent = NULL; /* set by pfdwb.c used by drt.c */
  164. int encrypted = 0;
  165.  
  166. /*----------------------------------------------*/
  167. /* It is crucial to share textures between      */
  168. /* files - so these lists store textures for     */
  169. /* sharing.                    */
  170. /*----------------------------------------------*/
  171.  
  172. static pfTexture    *sharedTexList[DWB_MAX_TEXTURES]; /* XXX - should grow */
  173. static pfTexEnv        *sharedTevList[DWB_MAX_TEXTURES]; /* XXX - should grow */
  174. static int         sharedTexCount = 0;
  175.  
  176. static pfVec4       nextBSplineColor; /* color to be attached to bspline */
  177.                       /* record when read */
  178. static pfSCS         *externSCSGroup; /* pointer to last extern SCS group read */
  179.  
  180.  
  181. typedef struct _ExternList
  182. {
  183.     char *name;
  184.     pfNode *node;
  185.     struct _ExternList *next;
  186. } ExternList;
  187.  
  188. typedef struct _ClipRegion
  189. {
  190.     pfChannel *channel;
  191.         int  chanSize[2];
  192.         int  chanOrigin[2];
  193.     float ll[3];
  194.     float ur[3];
  195.     short min[2];
  196.     short max[2];
  197.     int   gotOld;
  198.     short oldmin[2];
  199.     short oldmax[2];
  200.  
  201. } ClipRegion;
  202.  
  203. static ExternList *externs=NULL;
  204.  
  205. /*----------------------------------------------*/
  206. /* database counters                 */
  207. /*----------------------------------------------*/
  208.  
  209. static pfSCS        *childYupSCS;
  210.  
  211. /*========================================================================
  212.  *========================================================================
  213.  *
  214.  *                PROTOTYPES 
  215.  *
  216.  *========================================================================
  217.  *========================================================================*/
  218.  
  219.  
  220. static void    addLineToGeoState        (dwbGeoState *gstate, pfdGeom *polygon,
  221.                                         int drawStyle);
  222. static void    addLineList              (pfGeode *geode,dwbGeoState *gstate );
  223. static int     applyDetailTexture       (short texture, short detail);
  224. static void    cleanUp                  (void);
  225. static int    clipRegionOff            ( pfTraverser *trav, void *data );
  226. static int    clipRegionOn             ( pfTraverser *trav, void *data );
  227. static int    drawArc                  ( pfTraverser *trav, void *data );
  228. static void    dwbPop                   (pfNode **parent, pfNode **currentNode);
  229. static void    dwbPush                  (pfNode **parent, pfNode *currentNode);
  230. static void    freeLineList             (dwbGeoState *gstate );
  231. static dwbGeoState *getDwbGeoState      (void);
  232. static pfBillboard *getBillboard        (pfGeode *geode);
  233. static int     getDwbTexture            (int id);
  234. static pfMaterial *getPfMaterial        (dwbGeoState *gs);
  235. static int     handleArc                (memPtr *ifp, short length,
  236.                      pfNode *current,pfNode *parent);
  237. static int     handleBSpline            (memPtr *ifp, short length, 
  238.                                          pfNode *current, pfNode *parent);
  239. static int     handleColorTable         (memPtr *ifp);
  240. static int     handleComment            (memPtr *ifp, short length, 
  241.                                          pfNode *currentNode, pfNode *parent);
  242. static int     handleExternal           (memPtr *ifp,int length,pfNode *parent,
  243.                      pfNode **currNode);
  244. static void    handleDecal              (pfNode **parent );
  245. static int     handleFace               (memPtr *ifp, pfNode *parent, pfdGeom *poly,
  246.                       dwbGeoState **currentGState,int *vType,
  247.                     pfNode *current);
  248. static int     handleGroup              (memPtr *ifp, pfNode *parent, 
  249.                          pfNode **curr, int *faceType);
  250. static int     handleHeader             (memPtr *ifp, pfNode *currentNode);
  251. static int     handleInstanceDef        (memPtr *ifp, pfNode *currentNode,
  252.                                          pfNode *parent);
  253. static int     handleInstanceRef        (memPtr *ifp, pfNode *currentNode,
  254.                          pfNode *parentNode);
  255. static int     handleLightPoint         (memPtr *ifp, pfdGeom *polygon,
  256.                                          pfNode **parent, pfNode *current,
  257.                                          int vertType);
  258. static int     handleLineStyle          (memPtr *ifp, int size);
  259. static int     handleMaterial           (memPtr *ifp);
  260. static int     handleMatrix             (memPtr *ifp, pfNode **currentNode, 
  261.                                          pfNode *parent);
  262. static int     handlePackedVertex       (memPtr *ifp, int vertType, 
  263.                                          pfdGeom *polygon, short length);
  264. static int     handlePage               (memPtr *ifp, short length, 
  265.                                          pfNode *currentNode, pfNode *parent);
  266. static int     handleSwitch             (memPtr *ifp, pfNode *parent, 
  267.                                          pfNode **currentNode);
  268. static int     handleTexture            (memPtr *ifp);
  269. static int     handleVertex             (memPtr *ifp, int vertType, 
  270.                                          pfdGeom *polygon, short length);
  271. static void    initLoader               (void);
  272. static void    insertFaces              (pfNode *parent,int faceType);
  273. static dwbGeoState *makeDwbGeoState     (void);
  274. static pfGeoState *makePfGeoState       (dwbGeoState *gstate);
  275. static pfNode *loadDwbFile              (memPtr *ifp);
  276. static instRefList *newInstance         (void );
  277. static instRefList *getInstance         (short val);
  278. static memPtr  *openFile                 (char *fileName);
  279. static char   *readVariableLengthString (memPtr *ifp, int length);
  280. static void    setUpPolygonBindTypes    (pfdGeom *polyptr,int vert_type);
  281. static int     setZbufferOp             (pfTraverser *trav,void *data);
  282. static void    unCopyrightNotice        (void);
  283.        void    unPackRGBA               (unsigned int pcolor,float *rgba);
  284. static int     unsetZbufferOp           (pfTraverser *trav,void *data);
  285.  
  286. int memEof( memPtr *ptr);
  287. extern setRootNode (pfGroup *);
  288. extern drtEnd (pfNode *);
  289. extern int decode (dwbHeader *);
  290. extern mypfLoadTexFile (pfTexture *, char *);
  291. int map_viewport (ClipRegion *,pfChannel *, float *,float *,short *,short *);
  292. int initUserFuncs(void);
  293.  
  294.  
  295.  
  296. /*========================================================================
  297.  *========================================================================
  298.  *
  299.                        USER DEFINED FUNCTIONS
  300.  
  301.    An application can define a callback to be executed for almost every
  302.    dwbRecord. Callbacks are defined by calling setUserFunc with the appropriate
  303.    callback address and the RECORD type as defined in pfdwb.h
  304.  
  305.    The callback is called immediately after the record is read, and if it
  306.    returns a negative number the loader will abort any further processing of 
  307.    the record in question. A non negative return value will mean that the 
  308.    loader will continue as usual after the callback.
  309.  
  310.    The callback must accept the following as paramaters
  311.  
  312.     type - record type as defined by pfdwb.h
  313.     rec  - pointer to the record just read
  314.     current - pointer to the current Node position
  315.     parent - pointer to the parent of the current Node position
  316.         ifp  - pointer to the current position in the file.
  317.  
  318.  *
  319.  *========================================================================
  320.  *========================================================================*/
  321.  
  322.  
  323. /* macro to check the use defined functions of each opcode */
  324.  
  325. #define USERFUNCS(opcode,rec,curr,parent,ifp) \
  326.   if (  userFunctions[(opcode) - DB_HEADER].func != NULL) {    \
  327.     if ( userFunctions[(opcode) - DB_HEADER].func( (opcode),    \
  328.                       (rec), (curr), (parent),(ifp)) < 0)        \
  329.         return(1);                        \
  330.   }                                \
  331.  
  332. typedef struct _FuncEntry
  333. {
  334.   int (*func)(int type, void *rec, pfNode *current, pfNode *parent, memPtr *ifp);
  335. } FuncEntry;
  336.  
  337. static FuncEntry userFunctions[DB_LASTREC - DB_HEADER]; 
  338.  
  339. typedef struct _BsplineInfo
  340. {
  341.   int    numKnots;
  342.  
  343. #ifdef IRISGL  
  344.   double *knots;
  345.   double *cntlPnts;
  346. #else
  347.   GLfloat *knots;
  348.   GLfloat *cntlPnts;
  349.   GLUnurbsObj *nobj;
  350. #endif /* end GL type */
  351.  
  352.   pfVec4 color;
  353. } BsplineInfo;
  354.  
  355. typedef struct _ArcInfo
  356. {
  357.   float fRadius, fStartAngle, fEndAngle;
  358.   float matrix[4][4];
  359.   float pfNormal[3];
  360.   short drawstyle;
  361.   pfVec4 color;
  362. } ArcInfo;
  363.  
  364.  
  365.  
  366. static void removeRedundantGroups ( pfNode *_parent, pfNode *_node )
  367. {
  368. int type, i;
  369. pfNode *tmp;
  370.  
  371.   if ( _node && _parent != _node)
  372.   {
  373.   int nc;
  374.  
  375.     if (pfGetType(_node) == pfGetGroupClassType())
  376.     {
  377.       nc = pfGetNumChildren(_node);
  378.  
  379.       if (nc == 0)/* group with no children is useless(except callbacks!!)*/
  380.         pfRemoveChild(_node,tmp);
  381.       else if (nc == 1)/* remove intermediate group */
  382.       {
  383.         tmp = pfGetChild(_node,0);
  384.         pfReplaceChild(_parent,_node,tmp);
  385.         pfDelete(tmp);
  386.       }
  387.     }
  388.   }
  389.  
  390.   if (pfGetType(_node) == pfGetGroupClassType())
  391.   {
  392.   int nc = pfGetNumChildren(_node);
  393.  
  394.     /*
  395.      * Recurse on children.
  396.      */
  397.     for(i = 0; i < nc; i++)
  398.       removeRedundantGroups( _node, pfGetChild(_node,i) );
  399.   }
  400. }
  401.  
  402.  
  403.  
  404. /*========================================================================
  405.  *========================================================================
  406.  *
  407.  * ENTRY POINT from the outside world. Routine that will load a dwb file
  408.  * and convert that into a performer nodal tree. Returns a pointer to the
  409.  * first element in the tree.
  410.  *
  411.  *========================================================================
  412.  *========================================================================*/
  413.  
  414. extern pfNode *pfdLoad_dwb ( char *fileName )
  415. {
  416. memPtr *ifp;
  417. pfNode *node=NULL;
  418. short opcode;
  419.  
  420.   /* --------------------------------------- */
  421.   /* open file and check that it is readable */
  422.   /* --------------------------------------- */
  423.   if ( !(ifp = openFile( fileName )) )
  424.     return( NULL );
  425.  
  426.   /* ----------------------------------------------------- */
  427.   /* let the world know that this format is NON-proprietry */
  428.   /* ----------------------------------------------------- */
  429.   unCopyrightNotice();
  430.  
  431.   /* --------------------------------------------------------------- */
  432.   /* if the first opcode is not DB_HEADER then the format is _WRONG_ */
  433.   /* --------------------------------------------------------------- */
  434.   memRead(&opcode,sizeof(short),1,ifp);
  435.   if (opcode != DB_HEADER)
  436.   {
  437.     pfNotify(PFNFY_WARN,PFNFY_RESOURCE,
  438.     "LoadDwb: File format error. Cannot load %s",fileName);
  439.     if (opcode == 1)
  440.     {
  441.        pfNotify(PFNFY_WARN,PFNFY_RESOURCE,
  442.            "LoadDwb: Format could be early .flt");
  443.     }
  444.     cleanUp();
  445.   }
  446.   else
  447.   {
  448.     strncpy(dwbRoot->fname, fileName, PF_MAXSTRING);
  449.     memSeek(ifp, 0, SEEK_SET);
  450.     node = loadDwbFile( ifp );
  451.   }
  452.   
  453.  
  454. /*
  455.   {
  456.   FILE *ifp;
  457.  
  458.     ifp = fopen ("scene.out","w");
  459.     pfPrint(node, PFTRAV_SELF|PFTRAV_DESCEND, PFPRINT_VB_INFO, ifp);
  460.     fclose(ifp);
  461.   }
  462. */
  463. /*
  464.   removeRedundantGroups(node, node);
  465. */
  466.  
  467.   return (node);
  468. }
  469.  
  470.  
  471.  
  472.  
  473. /*========================================================================
  474.  * Real loading routine. Reads opcodes from the file and processes them
  475.  *======================================================================== */
  476. static pfNode *loadDwbFile( memPtr *ifp )
  477. {
  478. short opcode,length;
  479. pfGroup *top;
  480. pfNode *currentNode, *parentNode;
  481. int depth;
  482. int ok = 1;
  483. int renderFace = -99;
  484. dwbGeoState *currentGState;
  485. int vertType;
  486. /* allocate a new primitive buffer able to hold up to 256 vertices */
  487. pfdGeom *polygon = pfdNewGeom (256);
  488. int faceType;
  489. int titleCount=0;
  490.  
  491.   /* create top level container node */
  492.   top = pfNewGroup();
  493.  
  494.   dwbRoot->root = top;
  495.   currentNode = parentNode = (pfNode *) top;
  496.  
  497. #ifdef LINKLOADER
  498.   /* to allow top level links to work we need different parent/current nodes */
  499.   currentNode = (pfNode *) pfNewGroup();
  500.   pfAddChild(parentNode,currentNode); 
  501. #endif
  502.  
  503.   depth = 0;
  504.   /* ----------------------------------------------- */
  505.   /* main loop, reads each opcode and then calls the */
  506.   /* appropriate handling routines.                  */
  507.   /* ----------------------------------------------- */
  508.   while ( !memEof (ifp) && ok )
  509.   {
  510.     /* read the opcode and length */
  511.     memRead(&opcode,sizeof(short),1,ifp);
  512.     memRead(&length,sizeof(short),1,ifp);
  513.  
  514. #ifdef FANCY_TITLES
  515.     if (titleCount++ % 100 == 0)
  516.       drawBar(ifp->length,ifp->pos);
  517. #endif
  518.         switch ( opcode )
  519.         {
  520.             case DB_HEADER :
  521.         ok = handleHeader(ifp, currentNode);
  522.                 break;
  523.  
  524.             case DB_COLOR_TABLE:
  525.                 ok = handleColorTable(ifp);
  526.                 break;
  527.  
  528.             case DB_MATERIAL_TABLE:
  529.                 ok = handleMaterial(ifp);
  530.                 break;
  531.  
  532.             case DB_TEXTURE_TABLE:
  533.         ok = handleTexture(ifp);
  534.                 break;
  535.  
  536.  
  537.             case DB_GROUP:
  538.                 handleGroup(ifp,parentNode,¤tNode,&faceType);
  539.                 break;
  540.  
  541.  
  542.             case DB_FACE:
  543.         /* only attach faces when we go back to parent level */
  544.         renderFace = dwbRoot->treeDepth -1;
  545.                 ok = handleFace(ifp,parentNode,polygon,
  546.                 ¤tGState, &vertType,currentNode);
  547.                 break;
  548.  
  549.             case DB_SWITCH:  /* LOD */
  550.         handleSwitch(ifp, parentNode, ¤tNode);
  551.                 break;
  552.  
  553.            case DB_PUSH:
  554.         if (length > 0)
  555.                   memSeek(ifp,length,SEEK_CUR);
  556.  
  557.         dwbPush(&parentNode,currentNode);
  558.                 break;
  559.  
  560.            case DB_PACKED_VERTEX:
  561.         {
  562.                 int drawStyle = dwbRoot->currentGroup.drawstyle;
  563.  
  564.         handlePackedVertex(ifp,vertType, polygon,length);
  565.                 /* add verts to triangle or line set */
  566.                 if (polygon->numVerts < 3 ||
  567.                    (drawStyle != DS_SOLID && drawStyle != DS_SOLID_BOTH_SIDES))
  568.                      addLineToGeoState(currentGState,polygon,drawStyle);
  569.                 else if (currentGState->builder )
  570.                          pfdAddPoly( currentGState->builder, polygon);
  571.  
  572.         }
  573.         break;
  574.  
  575.          case DB_VERTEX:
  576.         {
  577.                 int drawStyle = dwbRoot->currentGroup.drawstyle;
  578.  
  579.         ok = handleVertex(ifp,vertType, polygon,length);
  580.                 /* add verts to triangle or line set */
  581.                 if (polygon->numVerts < 3 || 
  582.                    (drawStyle != DS_SOLID && drawStyle != DS_SOLID_BOTH_SIDES))
  583.                      addLineToGeoState(currentGState,polygon,drawStyle);
  584.  
  585.                 else if (currentGState->builder )
  586.                          pfdAddPoly( currentGState->builder, polygon);
  587.  
  588.         }
  589.         break;
  590.  
  591.          case DB_LIGHT_PT:
  592.         handleLightPoint(ifp,polygon,&parentNode,currentNode,vertType);
  593.                 vertType += LIGHTPOINT;
  594.         break;
  595.  
  596.            case DB_POP:
  597.         /* 
  598.          * Make sure we are back in the right level and also that the
  599.          * face.ptype is NOT BSpline.
  600.          */
  601.  
  602.         if (renderFace == dwbRoot->treeDepth -1 && 
  603.             currentFacePType != 3 && currentFacePType != 4) 
  604.                 {
  605.           insertFaces(parentNode,faceType);
  606.           renderFace = -99;
  607.           currentFacePType = -1;
  608.                 }
  609.  
  610.         if (length > 0)
  611.                   memSeek(ifp,length,SEEK_CUR);
  612.  
  613.         dwbPop(&parentNode,¤tNode);
  614.  
  615.         if ((! extendedVersion) || 
  616.             (extendedVersion && dwbRoot->renderGroup)) {
  617.           /* if we have just finished reading the verts for a face */
  618.           /* and that face is the first of a decal group */
  619.                   /* then decal that face */
  620.  
  621.           if (faceType == LAYER_BASE)
  622.                   {
  623.             handleDecal(&parentNode);
  624.             dwbRoot->renderGroup = 0;
  625.             faceType = LAYER_DECAL; /* only first face is decal */
  626.           }
  627.           else if (faceType == SEQUENCE) {
  628.             insertFaces (parentNode, SEQUENCE);
  629.                   }
  630.                 }
  631.               break;
  632.  
  633.             case DB_NAME_STR:
  634.                 /*----------------------------------------------*/
  635.                 /* all nodes except palettes & vertices have a  */
  636.                 /* name string immediately after the node       */
  637.                 /*----------------------------------------------*/
  638.         {
  639.           char *strVal;
  640.           strVal = readVariableLengthString(ifp,length);
  641.  
  642.           /* attach onto node name */
  643.           if (strlen(strVal) > 0)
  644.             pfNodeName(currentNode,strVal);
  645.  
  646.                   pfFree(strVal);
  647.         }
  648.                 break;
  649.  
  650.         case DB_VIEW_PARAMS:
  651.         memSeek(ifp,length,SEEK_CUR);
  652.         break;
  653.  
  654.         case DB_LINESTYLE_TABLE:
  655.         handleLineStyle(ifp,length);
  656.         break;
  657.  
  658.         case  DB_COMMENT :
  659.             handleComment(ifp,length,currentNode,parentNode);    
  660.                 break;
  661.  
  662.         case  DB_PAGE :
  663.             handlePage(ifp,length,currentNode,parentNode);    
  664.                 break;
  665.  
  666.         case  DB_IMAGE :
  667.         memSeek(ifp,length,SEEK_CUR);
  668.                 break;
  669.  
  670.         case  DB_LSOURCE :
  671.         memSeek(ifp,length,SEEK_CUR);
  672.                 break;
  673.  
  674.         case  DB_LMODEL :
  675.         memSeek(ifp,length,SEEK_CUR);
  676.                 break;
  677.  
  678.         case  DB_MATRIX :
  679.         handleMatrix(ifp, ¤tNode, parentNode);
  680.                 break;
  681.  
  682.         case DB_EXTERNAL:  /* external file reference */
  683.         ok = handleExternal(ifp,length,parentNode,¤tNode);
  684.         break;
  685.  
  686.         case DB_INSTANCE_DEF:
  687.            handleInstanceDef(ifp,currentNode,parentNode);
  688.         break;
  689.  
  690.         case DB_INSTANCE_REF:
  691.            handleInstanceRef(ifp,currentNode,parentNode);
  692.         break;
  693.  
  694.        /*list of opcodes that contain info that only the dwb tool requires*/
  695.         case DB_CONSTRUCTION:
  696.         case DB_TEXMAP:
  697.           /* skip past */
  698.           memSeek(ifp,length,SEEK_CUR);
  699.         break;
  700.  
  701.         case DB_BSPLINE:
  702.         handleBSpline(ifp,length,currentNode,parentNode);
  703.                 break;
  704.  
  705.             case DB_ARC:
  706.         handleArc(ifp, length, currentNode, parentNode);
  707.         break;
  708.  
  709.             default:
  710.         checkForLink( ifp, opcode, length, parentNode, ¤tNode,
  711.                   dwbRoot->treeDepth );
  712.                 break;
  713.         }
  714.   }
  715.  
  716.   /* 
  717.    * Some instances have been referenced before they were defined. Fix
  718.    * those.
  719.    */
  720.  
  721.   if (dwbRoot->refBeforeDef) {
  722.       refBeforeDefList *ptr = dwbRoot->refList;
  723.       pfSCS *scs;
  724.       instRefList *defPtr;
  725.       pfMatrix rot;
  726.  
  727.     while (ptr) {
  728.       defPtr = getInstance (ptr->inst.val);
  729.  
  730.       if (! defPtr) {
  731.         fprintf (stderr, "LoadDwb: Instance referenced but never defined\n");
  732.         continue;
  733.       }
  734.  
  735.       if ( dwbRoot->header.up_axis == Y_UP ) {
  736.         pfMakeEulerMat(rot,0.0,-90.0,0.0);
  737.         pfPostMultMat(ptr->inst.mat,rot);
  738.       }
  739.  
  740.       scs = pfNewSCS(ptr->inst.mat);
  741.       pfAddChild(ptr->parent, scs);
  742.       pfAddChild(scs, defPtr->node);
  743.  
  744.       ptr = ptr->next;
  745.     }
  746.   }
  747.     
  748.  
  749.   /* if the Y_UP flag is set then rotate the entire tree by -90 degrees */
  750.   if ( dwbRoot->header.up_axis == Y_UP )
  751.   {
  752.     pfSCS *scs;
  753.     pfMatrix rot;
  754.  
  755.     pfMakeEulerMat(rot,0.0,90.0,0.0);
  756.     scs = pfNewSCS(rot);
  757.     pfAddChild(scs,top);
  758.     top = (pfGroup *) scs;
  759.  
  760.     /* store this value so its visible to any parent thats loadin an external */
  761.     childYupSCS = scs;
  762.  
  763.     /* flatten any SCS nodes found */
  764.     /* Performer doesn't work correctly when nodes are shared - DONT do yet 
  765.     if (strstr(dwbRoot->fname, ".dwb") != NULL  && !externDepth)
  766.     {
  767.        pfFlatten(top,0); 
  768.     } */
  769.  
  770.     if (dwbRoot->containsInstancing ) {
  771.       printf("pfdwb:Warning...Model contains instancing and is Yup, may cause\n");
  772.       printf("orientation problems.\n");
  773.     }
  774.  
  775.  
  776.   }
  777.  
  778. #ifdef LINKLOADER
  779. /* this is the only time when the total tree is known - inform the drt loader */
  780.   setRootNode(top);
  781.   drtEnd(currentNode);
  782. #endif
  783.  
  784.   cleanUp();
  785.  
  786.   if (!ok)
  787.     printf("DwbLoader: Error in file format. \n");
  788.  
  789.   return ((pfNode *) top);
  790. }
  791.  
  792.  
  793. /*========================================================================
  794.  * free all temporary memory used by this iteration of the loader
  795.  *======================================================================== */
  796. static void cleanUp( void )
  797. {
  798. instRefList *ptr = dwbRoot->instList;
  799.  
  800.   if (dwbRoot)
  801.   {
  802.     if (dwbRoot->materials)     pfFree( dwbRoot->materials);
  803.     if (dwbRoot->materialTable) pfFree( dwbRoot->materialTable );
  804.     if (dwbRoot->textureTable)  pfFree( dwbRoot->textureTable );
  805.     if (dwbRoot->stack)         pfFree( dwbRoot->stack);
  806.  
  807.     if (lineStyles)
  808.       pfFree( lineStyles); /* free the local line style pallete */
  809. /*
  810.     while ( ptr)
  811.     {
  812.       ptr2 = ptr->next;
  813.       pfFree(ptr);
  814.       ptr = ptr2;
  815.     }
  816.  */   
  817.  
  818.     /* free up the geostates for this model */
  819.    if (dwbRoot->gsList)
  820.    {
  821.      dwbGeoState *tmp,*ptr = dwbRoot->gsList;
  822.      while(ptr)
  823.      {
  824.        tmp = ptr->next;
  825.        pfFree(tmp);
  826.        ptr = tmp;
  827.      }
  828.  
  829.    }
  830.    /* free up the memory buffer */
  831.    pfFree(dwbRoot->file.ptr);    
  832.  
  833.   }
  834.  
  835.   pfFree(dwbRoot);
  836.   dwbRoot = NULL;
  837. }
  838.  
  839.  
  840. /*========================================================================
  841.  * create a new entry in this files instance list 
  842.  *======================================================================== */
  843.  
  844. static instRefList *newInstance(void )
  845. {
  846. instRefList *ptr;
  847.  
  848.   ptr = pfCalloc(1, sizeof(instRefList), NULL);
  849.   if (dwbRoot->instList)
  850.     ptr->next = dwbRoot->instList;
  851.  
  852.   dwbRoot->instList = ptr;
  853.  
  854.   return(ptr);
  855. }
  856.  
  857.  
  858. static refBeforeDefList *newReference (void) {
  859.     refBeforeDefList *ptr;
  860.  
  861.   ptr = pfCalloc (1, sizeof(refBeforeDefList), NULL);
  862.   if (dwbRoot->refList)
  863.     ptr->next = dwbRoot->refList;
  864.  
  865.   dwbRoot->refList = ptr;
  866.  
  867.   return (ptr);
  868. }
  869.  
  870. /*========================================================================
  871.  * Search this files instance list and return the node that
  872.  * matches this instance value
  873.  *======================================================================== */
  874.  
  875. static instRefList *getInstance(short val)
  876. {
  877. instRefList *ptr = dwbRoot->instList;
  878.  
  879.   while (ptr)
  880.   {
  881.     if (ptr->inst.val == val)
  882.       return(ptr);
  883.  
  884.     ptr = ptr->next;
  885.   }
  886.   return(NULL);
  887. }
  888.  
  889.  
  890.  
  891.  
  892. /*========================================================================
  893.  * read an instance definition, and add that to
  894.  * the existing definitions for this file
  895.  *======================================================================== */
  896.  
  897. static int handleInstanceDef(memPtr *ifp, pfNode *currentNode,pfNode *parent)
  898. {
  899. instRefList *ptr;
  900.  
  901.   /* instance def refers to last node read */
  902.   /* so add the current node onto the instance list */
  903.   ptr = newInstance();
  904.  
  905.   memRead(&(ptr->inst),sizeof(dwbInstanceDef),1,ifp)
  906.   /* call any user functions for this opcode */
  907.   USERFUNCS(DB_INSTANCE_DEF,&ptr->inst,currentNode,parent,ifp);
  908.  
  909.   ptr->node = currentNode;
  910.   return(1);
  911.  
  912. }
  913.  
  914.  
  915. /*========================================================================
  916.  * read an instance reference, extract this references definition
  917.  * and then add the original definition into the tree at this point 
  918.  * The instance is not cloned so it shares ALL information with the
  919.  * original definition.
  920.  *======================================================================== */
  921.  
  922. static int handleInstanceRef(memPtr *ifp, pfNode *current, pfNode *parentNode)
  923. {
  924. dwbInstanceRef inst;
  925. instRefList *ptr;
  926. pfSCS *scs;
  927. pfMatrix rot;
  928.  
  929.   memRead(&inst,sizeof(dwbInstanceRef),1,ifp);
  930.   USERFUNCS(DB_INSTANCE_REF, &inst, current, parentNode,ifp);
  931.  
  932.   ptr = getInstance(inst.val);
  933.   if (!ptr)
  934.   {
  935.       refBeforeDefList *refPtr;
  936.  
  937.     printf("LoadDwb Warning: instance referenced before its defined \n");
  938.     dwbRoot->refBeforeDef = 1;
  939.     refPtr = newReference();
  940.     refPtr->parent = parentNode;
  941.     refPtr->inst = inst;
  942.     return (0);
  943.   }
  944.  
  945. /*pfFlatten stuff here */
  946.  
  947.   /* If pfFlatten was to be used then we should insert a dcs at this point */
  948.   /* to stop the flattening process flattening instanced geometry more than */
  949.   /* once. The manual says that pfFlatten will copy instanced nodes to avoid */
  950.   /* this problem but my test cases did not show this to be the case. */
  951.  
  952.   if ( dwbRoot->header.up_axis == Y_UP )
  953.   {
  954.     pfMakeEulerMat(rot,0.0,-90.0,0.0);
  955.     pfPostMultMat(inst.mat,rot);
  956.   }
  957.  
  958.  
  959.   /* give this instance its position and attach that to the tree */
  960.   scs = pfNewSCS(inst.mat);
  961.   pfAddChild(parentNode,scs);
  962.  
  963.   /* Instances share everything with the original instance */
  964.   /* so just attach the node again */ 
  965.   pfAddChild(scs,ptr->node);
  966.  
  967.   dwbRoot->containsInstancing = 1;
  968.  
  969.   return(1);
  970.  
  971. }
  972.  
  973.  
  974. /*========================================================================
  975.  * HandleLineStyle  - build the linestyle table
  976.  *======================================================================== */
  977.  
  978. static int handleLineStyle(memPtr *ifp, int size)
  979. {
  980. int numRecords;
  981. int count;
  982. dwbLineStyle lstyle;
  983.  
  984.   numRecords = size / sizeof(dwbLineStyle);
  985.  
  986.   lineStyles = pfCalloc( numRecords, sizeof(LineStyle),Arena);
  987.  
  988.   /* read in the records */
  989.   for (count =0; count < numRecords; count++)
  990.   {
  991.     memRead(&lstyle,sizeof(dwbLineStyle),1,ifp);
  992.     lineStyles[count].index = count;
  993.     lineStyles[count].style = lstyle.lstyle;
  994.   }
  995. }
  996.  
  997.  
  998. /*========================================================================
  999.  * Read a matrix record and attach that to the current position in
  1000.  * the performer tree. The currentNode is updates but the parent not
  1001.  * to ensure that when a pop is encountered the correct level is returned
  1002.  * to
  1003.  *======================================================================== */
  1004.  
  1005. static int handleMatrix( memPtr *ifp, pfNode **currentNode, pfNode *parent)
  1006. {                
  1007. pfSCS *scs;
  1008. pfMatrix mat;
  1009. dwbMatrix dwbMat;
  1010. float largest;
  1011.  
  1012.  
  1013.   /* --------------------------------------------- */
  1014.   /* Matrix always follows node that it references */
  1015.   /* just add a SCS for the currentNode            */
  1016.   /* --------------------------------------------- */
  1017.   memRead(&dwbMat,sizeof(dwbMatrix),1,ifp);
  1018.  
  1019.   USERFUNCS(DB_MATRIX, &dwbMat, *currentNode, parent,ifp);
  1020.  
  1021.   /* create a SCS node with the required matrix */
  1022.  
  1023.   if (externSCSGroup == (pfSCS *) *currentNode)
  1024.   {
  1025.  
  1026.     /* current node = external node with adjustment SCS already in place */
  1027.     /* need to make sure that the -90 rotation is placed BEFORE new matrix */
  1028.  
  1029.     pfGetSCSMat(externSCSGroup,mat);
  1030.     pfPostMultMat(mat,dwbMat.mat);
  1031.     pfCopyMat(mat, dwbMat.mat);
  1032.  
  1033.   }
  1034.   else 
  1035.     pfCopyMat(mat, dwbMat.mat);
  1036.   
  1037.   scs = pfNewSCS(mat);
  1038.  
  1039.   /* insert SCS infront of currentNode */
  1040.   pfRemoveChild(parent, *currentNode);
  1041.   pfAddChild(parent,scs);
  1042.   pfAddChild(scs,*currentNode);
  1043.  
  1044.   /* update the current node */
  1045.   *currentNode = (pfNode *)scs; 
  1046.  
  1047.  
  1048.   /* extract the scale value from the matrix and set that to the lod scale */
  1049.   /* this is not depth sensitive - EVERYTHING after this point will be scaled */
  1050.   /* by this amount */
  1051.  
  1052.   largest = dwbMat.mat[0][0];
  1053.   if (dwbMat.mat[1][1] > largest)
  1054.     largest = dwbMat.mat[1][1];
  1055.   if (dwbMat.mat[2][2] > largest)
  1056.     largest = dwbMat.mat[2][2];
  1057.  
  1058.   dwbRoot->lodScale = largest;
  1059.  
  1060.   return(1);
  1061. }
  1062.  
  1063. /*========================================================================
  1064.  * Read a comment and then call any user supplied calls
  1065.  * the loader does nothing with comment so this handling routine exists
  1066.  * solely for user callabcks.
  1067.  *======================================================================== */
  1068.  
  1069. static int handleComment( memPtr *ifp, short length, pfNode *currentNode, 
  1070.                           pfNode *parent)
  1071. {
  1072. short *space;
  1073.  
  1074.   space = pfMalloc(length,0);
  1075.   memRead(space,length,1,ifp);
  1076.  
  1077.   USERFUNCS(DB_COMMENT, space, currentNode, parent,ifp);
  1078.  
  1079.   pfFree(space);
  1080.  
  1081. }
  1082.  
  1083. static int handlePage( memPtr *ifp, short length, pfNode *currentNode, 
  1084.                           pfNode *parent)
  1085. {
  1086. dwbPage page;
  1087.  
  1088.   memRead(&page,length,1,ifp);
  1089.  
  1090.   USERFUNCS(DB_PAGE, &page, currentNode, parent,ifp);
  1091.  
  1092. #ifdef LINKLOADER
  1093.   {
  1094.     extern void addPageToList(int id);
  1095.     addPageToList(page.pageid);
  1096.   }
  1097. #endif
  1098. }
  1099.  
  1100. /*========================================================================
  1101.  * Read Header record and process it
  1102.  *======================================================================== */
  1103.  
  1104. static int handleHeader( memPtr *ifp, pfNode *currentNode )
  1105. {
  1106. int ok=1;
  1107.  
  1108.   /* -------------------------------------------------------- */
  1109.   /* read the header and set it into the global header record */
  1110.   /* A global record is used cause lots of things need access */
  1111.   /* to this structure.                           */ 
  1112.   /* -------------------------------------------------------- */
  1113.   memRead( &dwbRoot->header,sizeof(dwbHeader),1,ifp);
  1114.  
  1115. #ifndef ENCRYPT
  1116.     /* check that the object has the correct encryption */
  1117. #ifdef __ESCENE__
  1118.     if (!decode(&dwbRoot->header))
  1119.     {
  1120.       encrypted = 0;
  1121.     }
  1122.     else
  1123.       encrypted = 1;
  1124. #endif
  1125.  
  1126. #else
  1127.     if (!decode(&dwbRoot->header))
  1128.     {
  1129.       printf("Error: Attempt to load non demo model \n");
  1130.       exit(1);
  1131.     }
  1132. #endif
  1133.  
  1134.   USERFUNCS(DB_HEADER, &dwbRoot->header, currentNode, NULL,ifp);
  1135.  
  1136.   switch (dwbRoot->header.units)
  1137.   {
  1138.       case UT_FEET:
  1139.           dwbRoot->unitChange = (float)FEET_TO_METERS;
  1140.           break;
  1141.  
  1142.       case UT_INCHES:
  1143.           dwbRoot->unitChange = (float)INCHES_TO_METERS;
  1144.           break;
  1145.  
  1146.       case UT_KILOMETERS:
  1147.           dwbRoot->unitChange = (float)KM_TO_METERS;
  1148.           break;
  1149.  
  1150.       case UT_CENTIMETERS:
  1151.           dwbRoot->unitChange = (float)CM_TO_METERS;
  1152.           break;
  1153.  
  1154.       case UT_NAUTICAL_MILES:
  1155.           dwbRoot->unitChange = (float)NM_TO_METERS;
  1156.           break;
  1157.  
  1158.       default:
  1159.           dwbRoot->unitChange = 1.0;
  1160.           /*UT_METERS*/
  1161.           break;
  1162.   }
  1163.  
  1164.  
  1165.   if (dwbRoot->header.version < (LOWEST_DWB_FORMAT_VERSION_SUPPORTED 
  1166.                  - ROUNDING_ERROR) )
  1167.   {
  1168.     fprintf ( stderr,"\n\n" );
  1169.     fprintf ( stderr,"***** WARNING *****\n" );
  1170.     fprintf ( stderr,"*\n" );
  1171.     fprintf ( stderr,"* DWB2-Performer loader only supports format revision 2.1 and above\n" );
  1172.     fprintf ( stderr,"*\n" );
  1173.     fprintf ( stderr,"***** WARNING *****\n" );
  1174.     fprintf ( stderr,"\n\n" );
  1175.     return ( FALSE );
  1176.     }
  1177.  
  1178.   /* This is mainly for new Texture structures and Decal groups */
  1179.   if (dwbRoot->header.version > HIGHEST_DWB_FORMAT_VERSION_SUPPORTED -
  1180.                             ROUNDING_ERROR) {
  1181.     extendedVersion = 1;
  1182.   }
  1183.   else {
  1184.     extendedVersion = 0;
  1185.   }
  1186.  
  1187.  
  1188.   /* set up the overriding zbuffer state - if header says no zbuffering */
  1189.  
  1190.   if ( !dwbRoot->header.zbuffer)
  1191.       pfNodeTravFuncs ( currentNode,PFTRAV_DRAW,unsetZbufferOp,setZbufferOp );
  1192.  
  1193.   /* store up axis so that any externals can signal to there parent what */
  1194.   /* orientation that they have. This is used only in handleExternal */
  1195.   externChildYUp[externDepth] = dwbRoot->header.up_axis;
  1196.  
  1197.   return(ok);
  1198.  
  1199. }
  1200.  
  1201.  
  1202.  
  1203. /*========================================================================
  1204.  *
  1205.  * FUNCTION     : unCopyrightNotice
  1206.  * IN           : nothing
  1207.  * OUT          : nothing
  1208.  * DESCRIPTION  : make sure the world knows its using a Designer's Workbench
  1209.  *                file.
  1210.  *
  1211.  *========================================================================*/
  1212.  
  1213. static void unCopyrightNotice ( void )
  1214. {
  1215. static int firstTime =1;
  1216.  
  1217.   /* Only want the uncopyright notice once per application */
  1218.  
  1219.   if (firstTime)
  1220.   { 
  1221.     fprintf ( stderr,"==========================================================================\n" );
  1222.     fprintf ( stderr,"Coryphaeus Software DWB Version2.2 Loader for Iris Performer 1.2 04/25/94\n" );
  1223.     fprintf ( stderr,"==========================================================================\n" );
  1224.     fprintf ( stderr,"Unlimited License: The Designer's Workbench (DWB) loader software contained\n");
  1225.  
  1226.     fprintf ( stderr,"in this program is in the PUBLIC DOMAIN. There are NO restrictions in the\n");
  1227.     fprintf ( stderr,"use of this software. For further information about the loader and other \n" );
  1228.     fprintf ( stderr,"Performer related products contact: Coryphaeus Software, 985 University Av.\n" );
  1229.     fprintf ( stderr,"Suite 31, Los Gatos, CA 95030. Tel (408) 395-4537, Fax: (408) 395-6351\n");
  1230.     fprintf ( stderr,"==========================================================================\n" );
  1231.  
  1232. #ifdef ENCRYPT
  1233.     printf("\n\n--- Escene 2.0 Demo -- \n\n");
  1234. #endif
  1235.  
  1236.     firstTime = 0;
  1237.   }
  1238. }
  1239.  
  1240. /*========================================================================
  1241.  *
  1242.  * FUNCTION     : initLoader
  1243.  * DESCRIPTION  : init variables, counters etc
  1244.  *
  1245.  *========================================================================*/
  1246.  
  1247. static void initLoader ( void )
  1248. {
  1249. char gv[24];
  1250.    
  1251.   /*------------------------------------------*/
  1252.   /* Get Performer shared memory Arena        */
  1253.   /*------------------------------------------*/
  1254.   Arena = pfGetSharedArena();
  1255.  
  1256.   /*------------------------------------------*/
  1257.   /* Determine graphics configuration         */
  1258.   /*------------------------------------------*/
  1259.   GfxType = 0;
  1260.  
  1261. #ifdef IRISGL
  1262.   gversion(gv);
  1263.   if(strstr(gv, "RE") != NULL)
  1264.       GfxType |= GFX_REALITY;
  1265.  
  1266.   if(getgdesc(GD_MULTISAMPLE) == 1)
  1267.       GfxType |= GFX_MULTISAMPLE;
  1268. #else
  1269.   {
  1270.   int sharpen, multisample, trilinear = 1, detail;
  1271.  
  1272.     pfQueryFeature (PFQFTR_TEXTURE_SHARPEN, &sharpen);
  1273.     /* pfQueryFeature (PFQFTR_TEXTURE_TRILINEAR, &trilinear); */
  1274.     pfQueryFeature (PFQFTR_MULTISAMPLE, &multisample);
  1275.  
  1276.     /*
  1277.      * Is this a valid assumption?
  1278.      */
  1279.  
  1280.     if (sharpen && trilinear) GfxType |= GFX_REALITY;
  1281.     if (multisample) GfxType |= GFX_MULTISAMPLE;
  1282.   }
  1283. #endif /* end GL type */
  1284.  
  1285.   /*------------------------------------------*/
  1286.   /* Create Re-entrant safe  global variables */
  1287.   /*------------------------------------------*/
  1288.  
  1289.   if ((dwbRoot = pfCalloc(1,sizeof(dwbFile),NULL)) == NULL) {
  1290.     pfNotify (PFNFY_FATAL, PFNFY_RESOURCE, 
  1291.       "LoadDwb: Insufficient memory to load file\n");
  1292.   }
  1293.  
  1294.   if (!defTEnv) /* created once and once only */
  1295.     defTEnv = pfNewTEnv(Arena);
  1296.  
  1297.   /*------------------------------------------*/
  1298.   /* alloc max number of materials per file.. */
  1299.   /*------------------------------------------*/
  1300.   dwbRoot->materials = 
  1301.     (pfMaterial**) pfCalloc(DWB_MAX_MATERIALS, sizeof(pfMaterial*), NULL);
  1302.  
  1303.  
  1304. }
  1305.  
  1306.  
  1307.  
  1308.  
  1309.  
  1310. /*========================================================================
  1311.  * read a string into locally created memory. The caller is responsible
  1312.  * for freeing that memory
  1313.  *
  1314.  *========================================================================*/
  1315.  
  1316. static char *readVariableLengthString ( memPtr *ifp, int length )
  1317. {
  1318.     char *name;
  1319.  
  1320.     /* ----------------------------------------------------------------- */
  1321.     /* allocate space for the name and make sure that it is quad aligned */
  1322.     /* ----------------------------------------------------------------- */
  1323.     name = (char *) pfCalloc (((length/16)+ 1)*16,sizeof(int),NULL );
  1324.  
  1325.     memRead(name,sizeof(char),length,ifp);
  1326.     name[length] = '\0';
  1327.  
  1328.     if ( strlen(name) > (PF_MAXSTRING-1) )
  1329.         name[PF_MAXSTRING-1] = '\0';
  1330.  
  1331.     return ( name );                    /* Must be ok if we got this far */
  1332. }
  1333.  
  1334.  
  1335.  
  1336. /*========================================================================
  1337.  *
  1338.  * FUNCTION     : makeStructArray
  1339.  * IN           : number of structs to malloced,sizeof data & ptr to existing
  1340. data
  1341.  * OUT          : ptr to new array.
  1342.  * DESCRIPTION  : alloc array of structures.
  1343.  *
  1344.  *========================================================================*/
  1345.  
  1346. static void *makeStructArray ( int numstructs,int size,void *old_data_ptr )
  1347. {
  1348.     void *mptr = NULL;
  1349.     int new_data_size;
  1350.  
  1351.     if ( numstructs)
  1352.     {
  1353.         new_data_size = ((numstructs * size)/16 +1) *16;
  1354.  
  1355.         if ( old_data_ptr )     /* realloc required */
  1356.             mptr = pfRealloc ( old_data_ptr,new_data_size );
  1357.         else
  1358.             mptr = pfCalloc ( 1,(size /16 + 1)*16,NULL );
  1359.     }
  1360.  
  1361.     return ( mptr );
  1362. }
  1363.  
  1364.  
  1365. /*========================================================================
  1366.  *
  1367.  * FUNCTION     : handleTexture
  1368.  * IN           : current File Pointer
  1369.  * OUT          : success(1) or failure (0)
  1370.  * DESCRIPTION  : read the dwb texture record from disk
  1371.  *
  1372.  *========================================================================*/
  1373.  
  1374. static int handleTexture ( memPtr *ifp )
  1375. {
  1376. dwbOpcodeRec command;
  1377. char *fname;
  1378. dwbExtTexInfo texInfo;  /* New texture information structure */
  1379.  
  1380.   /* increase the space reserved for the material table */
  1381.   dwbRoot->textureTable = (dwbTexture *)
  1382.                   makeStructArray ( dwbRoot->texturesRead+1, sizeof(dwbTexture),
  1383.                                   (void *)dwbRoot->textureTable );
  1384.  
  1385.   /* update the quick access texture -> pfTex table */
  1386.   dwbRoot->pfTexIndex = 
  1387.                    makeStructArray( dwbRoot->texturesRead+1, sizeof(int),
  1388.                         (void *) dwbRoot->pfTexIndex);
  1389.  
  1390.   dwbRoot->pfTexIndex[dwbRoot->texturesRead] = -1;
  1391.  
  1392.   /* read in the material and increment the global material count   */
  1393.   /* Since the 1st few fields in version 3.0 and the lower versions */
  1394.   /* are the same, read in the contents into the same structure.    */
  1395.   /* But depending upon the version, the rest of the fields may or  */
  1396.   /* may not have valid information.                                */
  1397.   
  1398.   if (extendedVersion) {
  1399.     memRead(&texInfo,sizeof(dwbExtTexInfo),1,ifp);
  1400.   }
  1401.   else {
  1402.     memRead(&texInfo,sizeof(dwbTexInfo),1,ifp);
  1403.     /* bzero((void *)(&texInfo+sizeof (dwbTexInfo)), 
  1404.            sizeof(dwbExtTexInfo)-sizeof(dwbTexInfo));  */
  1405.   }
  1406.  
  1407.   /* read the texture name */
  1408.   memRead(&command, sizeof(dwbOpcodeRec),1,ifp);
  1409.   fname = readVariableLengthString(ifp,command.size); 
  1410.  
  1411.   if (extendedVersion)
  1412.   {
  1413.   dwbTexture tex;
  1414.  
  1415.     tex.name = fname;
  1416.     bcopy ((void *) &texInfo, (void *) &tex.tex, sizeof (dwbExtTexInfo));
  1417.     USERFUNCS (DB_TEXTURE_TABLE, &tex, NULL, NULL,ifp);
  1418.     bcopy ((void *) &tex.tex, (void *) &texInfo, sizeof (dwbExtTexInfo));
  1419.   }
  1420.   else USERFUNCS (DB_TEXTURE_TABLE, &texInfo, NULL, NULL,ifp);
  1421.  
  1422.   /* add new values to the texture table and increment counter */
  1423.   dwbRoot->textureTable[dwbRoot->texturesRead].name = fname; 
  1424.   dwbRoot->textureTable[dwbRoot->texturesRead++].tex = texInfo; 
  1425.  
  1426.  
  1427.   if (!fname )
  1428.     return(0);
  1429.   else
  1430.     return(1);
  1431.  
  1432. }
  1433.  
  1434.  
  1435.  
  1436. /*========================================================================
  1437.  *
  1438.  * FUNCTION     : handleMaterial
  1439.  * IN           : current File Pointer
  1440.  * OUT          : success(1) or failure (0)
  1441.  * DESCRIPTION  : read the dwb Material record from disk
  1442.  *
  1443.  *========================================================================*/
  1444.  
  1445. static int handleMaterial ( memPtr *ifp )
  1446. {
  1447.  
  1448.   /* increase the space reserved for the material table */
  1449.   dwbRoot->materialTable = (dwbMatInfo *)
  1450.                            makeStructArray ( dwbRoot->materialsRead+1, 
  1451.                               sizeof(dwbMatInfo),
  1452.                                              (void *)dwbRoot->materialTable );
  1453.  
  1454.   /* read in the material and increment the global material count */
  1455.   memRead(&(dwbRoot->materialTable[dwbRoot->materialsRead++]),
  1456.                   sizeof(dwbMatInfo),1,ifp);
  1457.  
  1458.   USERFUNCS(DB_MATERIAL_TABLE,&dwbRoot->materialTable[dwbRoot->materialsRead-1],
  1459.             NULL,NULL,ifp);
  1460.  
  1461.   return(1);
  1462.  
  1463. }
  1464.  
  1465. /*========================================================================
  1466.  *
  1467.  * FUNCTION     : readDwbColorPalette
  1468.  * IN           : nothing
  1469.  * OUT          : success(1) or failure (0)
  1470.  * DESCRIPTION  : read the dwb color table from disk & convert it to
  1471.  *                a floating pt RGB table in the dwbFile struct.
  1472.  *
  1473.  *========================================================================*/
  1474.  
  1475. static int handleColorTable ( memPtr *ifp )
  1476. {
  1477. register int x, y, z;
  1478. dwbColorTable fileValues;
  1479.  
  1480.   memRead(&fileValues,sizeof(dwbColorTable),1,ifp)
  1481.  
  1482.   USERFUNCS(DB_COLOR_TABLE, &fileValues, NULL, NULL,ifp);
  1483.  
  1484.   /*----------------------------------*/
  1485.   /* calculate variable color shades  */
  1486.   /*----------------------------------*/
  1487.   for(x=0; x<30; x++)
  1488.   {
  1489.     for(y=0; y<128; y++)
  1490.     {
  1491.       dwbRoot->colorTable[x*128+y][0]=
  1492.                                  (float)((fileValues.shaded[x][0]*y)/127)/255.0;
  1493.       dwbRoot->colorTable[x*128+y][1]=
  1494.                                  (float)((fileValues.shaded[x][1]*y)/127)/255.0;
  1495.       dwbRoot->colorTable[x*128+y][2]=
  1496.                                  (float)((fileValues.shaded[x][2]*y)/127)/255.0;
  1497.     }
  1498.   }
  1499.   /*----------------------------------*/
  1500.   /* fixed colors                     */
  1501.   /*----------------------------------*/
  1502.   x = 4096;
  1503.   for ( z=0; z<64; z++ )
  1504.   {
  1505.     dwbRoot->colorTable[x][0] = ( (float)fileValues.fixed[z][0] ) / 255.0;
  1506.     dwbRoot->colorTable[x][1] = ( (float)fileValues.fixed[z][1] ) / 255.0;
  1507.     dwbRoot->colorTable[x][2] = ( (float)fileValues.fixed[z][2] ) / 255.0;
  1508.  
  1509.     x++;
  1510.   }
  1511.   /*----------------------------------*/
  1512.   /* overlay colors                   */
  1513.   /*----------------------------------*/
  1514.   x = 4160;
  1515.   for ( z=0; z<16; z++ )
  1516.   {
  1517.     dwbRoot->colorTable[x][0] = ( (float)fileValues.overlay[z][0] ) / 255.0;
  1518.     dwbRoot->colorTable[x][1] = ( (float)fileValues.overlay[z][1] ) / 255.0;
  1519.     dwbRoot->colorTable[x][2] = ( (float)fileValues.overlay[z][2] ) / 255.0;
  1520.  
  1521.     x++;
  1522.   }
  1523.   /*----------------------------------*/
  1524.   /* underlay colors                  */
  1525.   /*----------------------------------*/
  1526.   x = 4176;
  1527.   for ( z=0; z<16; z++ )
  1528.   {
  1529.     dwbRoot->colorTable[x][0] = ( (float)fileValues.underlay[z][0] ) / 255.0;
  1530.     dwbRoot->colorTable[x][1] = ( (float)fileValues.underlay[z][1] ) / 255.0;
  1531.     dwbRoot->colorTable[x][2] = ( (float)fileValues.underlay[z][2] ) / 255.0;
  1532.  
  1533.     x++;
  1534.   }
  1535.  
  1536.   return (TRUE);   /* Must be ok if we got this far */
  1537. }
  1538.  
  1539.  
  1540.  
  1541.  
  1542.  
  1543. /*========================================================================
  1544.  * When an external is received the load routines are called recursively
  1545.  * with the new file name. Parent and current node are not reset though
  1546.  * and will continue adding to the performer tree from the calling point
  1547.  *========================================================================*/
  1548. static pfNode *reuseExtern(char *name )
  1549. {
  1550. ExternList *ptr = externs;
  1551.  
  1552.   while (ptr)
  1553.   {
  1554.     if (!strcmp(ptr->name,name))
  1555.     {
  1556.       printf("Reusing Extern %s\n",name);
  1557.       return(ptr->node);
  1558.     }
  1559.     ptr = ptr->next;
  1560.   }
  1561.  
  1562.   /* else add new extern onto list */
  1563.   printf("Creating Extern...%s\n",name);
  1564.   ptr = pfCalloc(1, sizeof(ExternList),0);
  1565.   ptr->name = name;
  1566.   ptr->next = externs;
  1567.   externs = ptr;
  1568.  
  1569.   return(0); 
  1570. }
  1571.  
  1572.  
  1573.  
  1574.  
  1575.  
  1576.  
  1577.  
  1578.  
  1579.  
  1580. /*========================================================================
  1581.  * read an external record, and then process it.
  1582.  * This routine makes use of the re-entrant nature of the loader and 
  1583.  * recursively calls the top load routine. Which returns a pointer to
  1584.  * a node that is then attached to the current position.
  1585.  * An external will generally be followed by a matrix record, this routine
  1586.  * ensures that the correct tree structure is present for the matrix record
  1587.  *========================================================================*/
  1588.  
  1589. static int handleExternal(memPtr *ifp,int length,pfNode *parent,pfNode **currNode)
  1590. {
  1591. char *str;
  1592. pfNode *extNode;
  1593.  
  1594.   USERFUNCS(DB_EXTERNAL, NULL, *currNode, parent,ifp);
  1595.  
  1596.   str = readVariableLengthString(ifp,length);
  1597.   extNode = reuseExtern(str);
  1598.   if (!extNode)
  1599.   {
  1600.     if (externDepth > MAX_EXTERN_DEPTH)
  1601.     {
  1602.        printf("Error: Too many nested externals \n");
  1603.        return 0;
  1604.     }
  1605.  
  1606.     dwbRoot->insideExternal = 1;
  1607.     externArray[externDepth++] = dwbRoot;
  1608.     if ((extNode = pfdLoad_dwb(str)) == NULL) return 1;
  1609.     externDepth--;
  1610.     dwbRoot = externArray[externDepth];
  1611.     dwbRoot->insideExternal = 0;
  1612.  
  1613.     /* 
  1614.      * Now we need to work the matrices so that the matrix which follows
  1615.      * this record is placed into the correct coordinate frame.
  1616.      * It all rests on whether the parent is Y-up and whether the external
  1617.      * is Y-up. Placing a value int externSCSGroup will ensure that the next
  1618.      * matrix record read will get placed AFTER that group.
  1619.      * if either Y-Up,  then there will be a 90 rotation matrix at its root 
  1620.      *
  1621.      * 4 Possibilites:
  1622.     Parent Y-up, child Y-up: Already a rot matrix so remove the childs matrx
  1623.     Parent Y-up, child Not Y-up: add a -90 rotation to child
  1624.     Parent NOT Y-up, child Y-up: ok - record SCS so that matrix can get 
  1625.                                      placed after SCS
  1626.     Parent NOT Y-up, child Not Y-up: ok no changes needed
  1627.     The global variable used to check is not re-entrant so an nested globals
  1628.     MUSt have the same orientation as the initial external
  1629.      */
  1630.  
  1631.     if ( dwbRoot->header.up_axis == Y_UP && externChildYUp[externDepth+1] != Y_UP ) 
  1632.     {
  1633.       pfSCS *scs;
  1634.       pfMatrix rot;
  1635.  
  1636.       pfMakeEulerMat(rot,0.0,-90.0,0.0);
  1637.       scs = pfNewSCS(rot);
  1638.       pfAddChild(scs,extNode);
  1639.  
  1640.       extNode = (pfNode *) scs;
  1641.  
  1642.       /* set global variable to allow the next matrix record to be positioned */
  1643.       /* after this scs orientation */
  1644.       externSCSGroup = scs;
  1645.     }
  1646.     else if (dwbRoot->header.up_axis == Y_UP && externChildYUp[externDepth+1] == Y_UP)
  1647.     {
  1648.       pfNode *node;
  1649.  
  1650.       /* remove the Y-up orientation from the nested file */
  1651.       if (childYupSCS)
  1652.       {
  1653.         node = pfGetChild(childYupSCS,0);
  1654.         pfRemoveChild(childYupSCS,node);
  1655.         pfDelete(childYupSCS);
  1656.         extNode = node; 
  1657.         externSCSGroup = NULL;
  1658.       }
  1659.       else
  1660.       printf("Internal Error:No Yup orientation matrix defined for external\n");
  1661.     }
  1662.     else if (dwbRoot->header.up_axis != Y_UP && externChildYUp[externDepth+1]==Y_UP)
  1663.       externSCSGroup = (pfSCS *) extNode;
  1664.  
  1665.  
  1666.  
  1667.     externs->node = extNode;
  1668.   }
  1669.  
  1670.   /* attach the returned node onto the current tree position */
  1671.   pfAddChild(parent,extNode);
  1672.  
  1673.   /* update the current node */
  1674.   *currNode = extNode;
  1675.   return(1);
  1676.  
  1677. }
  1678.  
  1679.  
  1680. /*========================================================================
  1681.  *
  1682.  * FUNCTION     : unsetZbufferOp
  1683.  * IN           : pfTraverser pointer (unused) & operation ID
  1684.  * OUT          :
  1685.  * DESCRIPTION  : unset GL zbuffer before traversing a particular  Node.
  1686.  *                Ignore incoming parameters.
  1687.  *
  1688.  *========================================================================*/
  1689.  
  1690. static int unsetZbufferOp ( pfTraverser *trav,void *data )
  1691. {
  1692. #ifdef IRISGL
  1693.   int zbuffval = getzbuffer();
  1694.  
  1695.   if (zbuffval) zbuffer ( FALSE );
  1696. #else
  1697.   GLboolean zbuffval = glIsEnabled (GL_DEPTH_TEST);
  1698.  
  1699.   if (zbuffval == GL_TRUE) glDisable (GL_DEPTH_TEST);
  1700. #endif /* end GL type */
  1701.   return ( 1 );
  1702. }
  1703.  
  1704.  
  1705.  
  1706.  
  1707. /*========================================================================
  1708.  *
  1709.  * set zbuffer on inside a draw callback
  1710.  *
  1711.  *========================================================================*/
  1712.  
  1713. static int setZbufferOp ( pfTraverser *trav,void *data )
  1714. {
  1715. #ifdef IRISGL
  1716.   int zbuffval = getzbuffer();
  1717.  
  1718.   if (! zbuffval) zbuffer (TRUE );
  1719. #else
  1720.   GLboolean zbuffval = glIsEnabled (GL_DEPTH_TEST);
  1721.  
  1722.   if (zbuffval == GL_FALSE) glEnable (GL_DEPTH_TEST);
  1723. #endif /* end GL type */
  1724.  
  1725.   return ( 1 );
  1726. }
  1727.  
  1728.  
  1729. /*
  1730.  * Take the bounding box from the current group and put that into
  1731.  * a Performer Sphere structure. This sphere structure 
  1732.         groupBoundingSphere
  1733.  * is global and is available to any child of the group to access.
  1734.  * Currently the only thing which needs this is the support for
  1735.  * bsplines. Note. its value is not preserved if an external is
  1736.  * processed, so there could be conditions when it is not correct
  1737.  * Add it to the dwbRoot structure to get around this if it causes
  1738.  * problems
  1739.  */
  1740.  
  1741. static void setBoundingSphereRadius(pfNode *currentNode,float *bbox)
  1742. {
  1743. float units;
  1744. pfSphere *sph = &groupBoundingSphere;
  1745. pfVec3 pnts[2];
  1746.  
  1747.   units = dwbRoot->unitChange;
  1748.  
  1749.   /* given the two corners of the bounding box compute */
  1750.   /* the radius of the sphere needed to cut that */
  1751.   pnts[0][0] = bbox[0] * units; pnts[1][0] = bbox[1] * units;
  1752.   pnts[0][1] = bbox[2] * units; pnts[1][1] = bbox[3] * units;
  1753.   pnts[0][2] = bbox[4] * units; pnts[1][2] = bbox[5] * units;
  1754.  
  1755.   pfSphereAroundPts(sph,pnts,2);
  1756. }
  1757.  
  1758. static int setLineStyleOn ( pfTraverser *trav, void *data )
  1759. {
  1760. LineStyle *style = (LineStyle*) data;
  1761. static short firstTime = 1;
  1762.  
  1763. #ifdef IRISGL
  1764.   if (firstTime)
  1765.   {
  1766.     deflinestyle(style->index,style->style);
  1767.     lsrepeat(8);
  1768.     firstTime = 0;
  1769.   }
  1770.  
  1771.   setlinestyle(style->index);
  1772. #else
  1773.   if (firstTime)
  1774.   {
  1775.     glNewList ((GLuint) data, GL_COMPILE);
  1776.     glLineStipple (8, style->style);
  1777.     glEndList ();
  1778.     firstTime = 0;
  1779.   }
  1780.  
  1781.   glEnable (GL_LINE_STIPPLE);
  1782.   glCallList ((GLuint) data);
  1783. #endif /* end GL type */
  1784. }
  1785.  
  1786. static int setLineStyleOff ( pfTraverser *trav, void *data )
  1787. {
  1788. #ifdef IRISGL
  1789.   setlinestyle (0);
  1790. #else
  1791.   glDisable (GL_LINE_STIPPLE);
  1792. #endif /* end GL type */
  1793. }
  1794.  
  1795.  
  1796. /*========================================================================
  1797.  *
  1798.  * Do all the processing associated with a group. As groups in dwb cover
  1799.  * a variety of tasks ranging from simple containers all the way down
  1800.  * to Decal groups this module is necessarily large
  1801.  *
  1802.  *========================================================================*/
  1803.  
  1804. static int handleGroup(memPtr *ifp, pfNode *parent, pfNode **curr, int *faceType)
  1805. {
  1806. pfNode *currentNode;
  1807. int ok;
  1808. dwbGroup group;
  1809. dwbHeader *dwb_header = &dwbRoot->header;
  1810. groupValues *currentGroup = &dwbRoot->currentGroup;
  1811.  
  1812.   /* -------------------------------------------- */
  1813.   /* No matter what create a group container node */
  1814.   /* -------------------------------------------- */
  1815.   currentNode = (pfNode *) pfNewGroup();
  1816.   pfAddChild(parent,currentNode);
  1817.  
  1818.   /* read the group */
  1819.   memRead( &group, sizeof(dwbGroup),1,ifp);
  1820.  
  1821.   if (group.grp_flags.sequence == 0 || group.grp_flags.decal == 0) {
  1822.     if (! extendedVersion) {
  1823.       USERFUNCS(DB_GROUP, &group, currentNode, parent,ifp);
  1824.     }
  1825.     else {
  1826.       /* 
  1827.        * If the renderGrp flag is set, then treat this group as an
  1828.        * older version group
  1829.        */
  1830.       if (group.grp_flags.renderGrp) {
  1831.     dwbRoot->renderGroup = 1;
  1832.     USERFUNCS(DB_GROUP, &group, currentNode, parent,ifp);
  1833.       }
  1834.       else dwbRoot->renderGroup = 0;
  1835.     }
  1836.   }
  1837.  
  1838.   setBoundingSphereRadius(currentNode,group.bbox);
  1839.  
  1840.   if (group.grp_flags.decal) {
  1841.     if (! extendedVersion) {
  1842.       *faceType = LAYER_BASE;
  1843.     }
  1844.     else {
  1845.       /*
  1846.        * Older version of handling Decals and the newer version of handling
  1847.        * decals when renderGrp flag is set are the same.
  1848.        */
  1849.       if (group.grp_flags.renderGrp) {
  1850.     *faceType = LAYER_BASE;
  1851.       }
  1852.       else {
  1853.       pfLayer *temp;
  1854.         temp = pfNewLayer();
  1855.  
  1856.         pfReplaceChild (parent, currentNode, temp);
  1857.  
  1858.     {
  1859.     short pfdecalmode;
  1860.       switch (group.decal_type)
  1861.       {
  1862.         case DWB_DECAL_BASE_FAST: 
  1863.           pfdecalmode = PFDECAL_BASE_FAST; 
  1864.         break;
  1865.  
  1866.         case DWB_DECAL_BASE_HIGH_QUALITY:
  1867.           pfdecalmode = PFDECAL_BASE_HIGH_QUALITY;
  1868.         break;
  1869.  
  1870.         case DWB_DECAL_BASE_STENCIL:
  1871.           pfdecalmode = PFDECAL_BASE_STENCIL;
  1872.         break;
  1873.  
  1874.         case DWB_DECAL_BASE_DISPLACE:
  1875.           pfdecalmode = PFDECAL_BASE_DISPLACE;
  1876.         break;
  1877.  
  1878.         default:
  1879.           fprintf (stderr, "loadDwb: unknown Decal mode\n");
  1880.           pfdecalmode = PFDECAL_BASE_FAST;
  1881.         break;
  1882.       }
  1883.           pfLayerMode(temp, pfdecalmode);
  1884.     }
  1885.  
  1886.         currentNode = (pfNode *) temp;
  1887.         USERFUNCS (DB_GROUP, &group, currentNode, parent, ifp);
  1888.         *faceType = NORMAL;
  1889.       }
  1890.     }
  1891.   }
  1892.   else if  (group.grp_flags.billboard)
  1893.          *faceType = BILLBOARD;
  1894.   else if  (group.grp_flags.sequence)
  1895.   {
  1896.     pfSequence *seq;
  1897.  
  1898.     /* add a sequence to the tree */
  1899.     seq = pfNewSeq();
  1900.     pfSeqTime(seq, PFSEQ_ALL, group.seq_time);
  1901.  
  1902.     {
  1903.     short pfseqmode;
  1904.  
  1905.       switch (group.seq_mode)
  1906.       {
  1907.     case DWB_SEQ_CYCLE:
  1908.       pfseqmode = PFSEQ_CYCLE;
  1909.     break;
  1910.  
  1911.     case DWB_SEQ_SWING:
  1912.       pfseqmode = PFSEQ_SWING;
  1913.     break;
  1914.  
  1915.     default:
  1916.       fprintf (stderr, "loadDwb: Unknown sequence mode\n");
  1917.       pfseqmode = PFSEQ_CYCLE;
  1918.     break;
  1919.       }
  1920.  
  1921.       pfSeqInterval(seq, pfseqmode, group.seq_bgn, group.seq_end);
  1922.     }
  1923.  
  1924.     pfSeqDuration(seq,group.seq_speed,group.seq_nreps);
  1925.     pfSeqMode(seq, PFSEQ_START);
  1926.  
  1927.     pfReplaceChild (parent, currentNode, seq);
  1928.     currentNode = (pfNode *) seq;
  1929.  
  1930.     USERFUNCS(DB_GROUP, &group, currentNode, parent,ifp);
  1931.  
  1932.     *faceType = SEQUENCE;
  1933.   }
  1934.   else if (group.grp_flags.clip_region)
  1935.   {
  1936.   ClipRegion *clip;
  1937.   int switchOn(pfTraverser *trav, void *data);
  1938.  
  1939.      clip = pfCalloc(1, sizeof(ClipRegion),Arena);
  1940.      memcpy(clip->ll,&group.ll,sizeof(float)*3);
  1941.      memcpy(clip->ur,&group.ur,sizeof(float)*3);
  1942.  
  1943.      pfNodeTravFuncs(currentNode,PFTRAV_CULL,switchOn, NULL); 
  1944.  
  1945.      pfNodeTravFuncs(currentNode, PFTRAV_DRAW,clipRegionOn,clipRegionOff);
  1946.      pfNodeTravData(currentNode, PFTRAV_DRAW, (void *) clip);
  1947.      *faceType = NORMAL; 
  1948.   }  
  1949.   else {
  1950.     *faceType = NORMAL;
  1951.   }
  1952.  
  1953.   /* set up new current node */
  1954.   *curr = currentNode;
  1955.  
  1956.   /*--------------------------------------------------*/
  1957.   /* set up the backface mode for this group.         */
  1958.   /*--------------------------------------------------*/
  1959.   if ( dwb_header->backface == TS_SELECTIVE )
  1960.       currentGroup->backface = group.gfx_flags.backface;
  1961.   else
  1962.       currentGroup->backface = dwb_header->backface;
  1963.  
  1964.  
  1965.   /*--------------------------------------------------*/
  1966.   /* set up the drawstyle mode for this group. For    */
  1967.   /* now - we are only interested in solid & wire.    */
  1968.   /*--------------------------------------------------*/
  1969.   if ( dwb_header->drawstyle == DS_SELECTIVE )
  1970.   {
  1971.     switch  ( group.drawstyle )
  1972.     {
  1973.         case DS_POINTS:
  1974.         case DS_OPEN_WIRE:
  1975.         case DS_CLOSED_WIRE:
  1976.             currentGroup->drawstyle = group.drawstyle;
  1977.             break;
  1978.         default:
  1979.             currentGroup->drawstyle = DS_SOLID;
  1980.             break;
  1981.     }
  1982.   }
  1983.   else
  1984.       currentGroup->drawstyle = dwb_header->drawstyle;
  1985.  
  1986.   /*--------------------------------------------------*/
  1987.   /* set up the zbuffer mode for this group.          */
  1988.   /*--------------------------------------------------*/
  1989.   if ( dwb_header->zbuffer == TS_SELECTIVE )
  1990.   {
  1991.     currentGroup->zbuffer = group.gfx_flags.zbuffer;
  1992.  
  1993.     /*----------------------------------------------*/
  1994.     /* check the zbuffer state for this group.If its*/
  1995.     /* OFF and its selective zbuffering we will zap */
  1996.     /* the  zbuffer FOR THIS NODE ONLY.             */
  1997.     /*----------------------------------------------*/
  1998.  
  1999.     if ( ! currentGroup->zbuffer )
  2000.       pfNodeTravFuncs ( currentNode,PFTRAV_DRAW,unsetZbufferOp,setZbufferOp );
  2001.  
  2002.   }
  2003.   else
  2004.     currentGroup->zbuffer = dwb_header->zbuffer;
  2005.  
  2006.   /*--------------------------------------------------*/
  2007.   /* set up the shademodel for the renderable nodes.  */
  2008.   /* Either use group shademodel or the global ones.  */
  2009.   /*--------------------------------------------------*/
  2010.   if ( dwb_header->shademodel == SM_SELECTIVE )
  2011.     currentGroup->shading = group.shademodel;
  2012.   else
  2013.     currentGroup->shading = dwb_header->shademodel;
  2014.  
  2015.   /*--------------------------------------------------*/
  2016.   /* only light the group if the group shading is     */
  2017.   /* illuminated...in a  Designer's Workbench file    */
  2018.   /* FLAT means 1 color per primitive - non lit,      */
  2019.   /* GOURAUD means 1 color per vertex - non lit and   */
  2020.   /* ILLUMINATED means lit using lmcolor              */
  2021.   /*--------------------------------------------------*/
  2022.   if ( currentGroup->shading == SM_ILLUMINATED )
  2023.   {
  2024.     /*----------------------------------------------*/
  2025.     /* set illumination binding                     */
  2026.     /*----------------------------------------------*/
  2027.     if ( dwb_header->material_binding == MB_SELECTIVE )
  2028.       currentGroup->binding = group.material_binding;
  2029.     else
  2030.       currentGroup->binding = dwb_header->material_binding;
  2031.  
  2032.     currentGroup->material = group.material;
  2033.     currentGroup->alpha = dwbRoot->materialTable[group.material].mat.alpha;
  2034.  
  2035.     /*----------------------------------------------*/
  2036.     /* defensive programming here because some      */
  2037.     /* older dwb files could have group shading set */
  2038.     /* to ILLUMINATED but actually be referencing   */
  2039.     /* index -1.                                    */
  2040.     /*----------------------------------------------*/
  2041.     if ( currentGroup->material == -1 )
  2042.     {
  2043.       currentGroup->shading = SM_FLAT_NON_LIT;
  2044.       currentGroup->alpha   = 1.0;
  2045.       currentGroup->binding = MB_LIGHTING_OFF;
  2046.     }
  2047.   }
  2048.   else
  2049.   {
  2050.     currentGroup->material = -1;
  2051.     currentGroup->binding  = MB_LIGHTING_OFF;
  2052.     /*----------------------------------------------*/
  2053.     /* check group-level transparency - use this for*/
  2054.     /* non lit models. Lit models will use the      */
  2055.     /* transparency  in the material definition.    */
  2056.     /*----------------------------------------------*/
  2057.     if ( group.transparency != 1.0 /*&& dwb_header->transparency*/ )
  2058.       currentGroup->alpha = group.transparency;
  2059.     else
  2060.       currentGroup->alpha = 1.0;
  2061.   }
  2062. }
  2063.  
  2064.  
  2065.  
  2066.  
  2067.  
  2068. /* --------------------------------------------------------------------- */
  2069. /* implement a simple dynamic length stack that is used to store the   */
  2070. /* parent and current node information at every push and pop encountered */
  2071. /* --------------------------------------------------------------------- */
  2072.  
  2073. printStack( void )
  2074. {
  2075. int count;
  2076. treeStack *stack = dwbRoot->stack;
  2077.  
  2078.   for (count=0; count < dwbRoot->treeDepth; count++)
  2079.     printf("%d : %x \t\t: %x\n",count, stack[count].parent, stack[count].current);
  2080.  
  2081. }
  2082.  
  2083.  
  2084.  
  2085. static void dwbPush(pfNode **parent, pfNode *currentNode)
  2086. {
  2087.  
  2088.   if (dwbRoot->treeDepth+1 > dwbRoot->stackDepth)
  2089.   {
  2090.     /* increase the size of the stack by STACKSIZE */
  2091.     dwbRoot->stackDepth += STACKSIZE;
  2092.     if (!dwbRoot->stack)
  2093.       dwbRoot->stack =(treeStack*) pfMalloc(sizeof(treeStack)*dwbRoot->stackDepth,                                            NULL);
  2094.     else
  2095.       dwbRoot->stack =(treeStack*) makeStructArray(dwbRoot->stackDepth,
  2096.                                  sizeof(treeStack), dwbRoot->stack);
  2097.   }
  2098.  
  2099.   dwbRoot->stack[dwbRoot->treeDepth].parent = *parent;
  2100.   dwbRoot->stack[dwbRoot->treeDepth].current = currentNode;
  2101.  
  2102.   *parent = currentNode;
  2103.   dwbRoot->treeDepth++;
  2104. }
  2105.  
  2106. static void dwbPop(pfNode **parent, pfNode **currentNode)
  2107. {
  2108.   /* dwb2 will store one more pop than necessary - check for that */ 
  2109.   if (dwbRoot->treeDepth > 0)
  2110.     dwbRoot->treeDepth--;
  2111.  
  2112.   *parent      = dwbRoot->stack[dwbRoot->treeDepth].parent;
  2113.   *currentNode = dwbRoot->stack[dwbRoot->treeDepth].current;
  2114. }
  2115.  
  2116.  
  2117.  
  2118.  
  2119.  
  2120.  
  2121. /*========================================================================
  2122.  *
  2123.  * Process a Switch Record
  2124.  * doesnt use lods the way Performer expects yet 
  2125.  * these lod nodes will only ever contain one object and it is 
  2126.  * either on or off depending on range 
  2127.  * later version will compact all lods with adjacent ranges into single 
  2128.  * lod nodes 
  2129.  *
  2130.  *========================================================================*/
  2131.  
  2132. static int handleSwitch(memPtr *ifp, pfNode *parent, pfNode **currentNode)
  2133. {
  2134. float unitChange = dwbRoot->unitChange;
  2135. dwbSwitch sw;
  2136. float buff[3];
  2137. pfLOD *lod;
  2138. pfGroup *tmp;
  2139.  
  2140.   memRead(&sw,sizeof(dwbSwitch),1,ifp);
  2141.  
  2142.   /* only support switches on distance */
  2143.   if (sw.switchtype == ST_DISTANCE)
  2144.   {
  2145.     lod = pfNewLOD();     
  2146.     pfAddChild(parent,lod);
  2147.  
  2148.     USERFUNCS(DB_SWITCH, &sw, (pfNode *) lod, parent,ifp);
  2149.  
  2150.     /* set the switch distances */
  2151.     pfLODRange ( lod, 0, sw.switchout*unitChange ); 
  2152.     pfLODRange ( lod, 1, sw.switchin*unitChange ); 
  2153.  
  2154.     copyNyup(buff,sw.center,unitChange)
  2155.  
  2156.     /* set the centre */
  2157.     pfLODCenter( lod, buff );
  2158.  
  2159.     /* now create a single group for all nested children to reference */
  2160.    tmp = pfNewGroup();
  2161. #if LINKLOADER
  2162.    LODChild = (pfNode *)tmp; /* only of relevance to drt.c */
  2163.    LODParent = (pfNode *)lod; /* only of relevance to drt.c */
  2164. #endif
  2165.  
  2166.    pfAddChild(lod,tmp);
  2167.     *currentNode = (pfNode *) tmp;
  2168.   }
  2169.   else {
  2170.     printf("Switch node contains thresholding - NOT YET SUPPORTED\n");
  2171.     /*
  2172.      * Make sure that the hierarchy is readjusted for lack of node 
  2173.      * creation.
  2174.      */
  2175.     *currentNode = parent;
  2176.   }
  2177.  
  2178.   return(1);
  2179. }
  2180.  
  2181.  
  2182.  
  2183.  
  2184.  
  2185.  
  2186. /*========================================================================
  2187.  *
  2188.  * Read a face record and set up the variables needed to
  2189.  * later create the GeoSets when the vertices are read:
  2190.  
  2191.     polygon: will contain the vertices,colours, and normals values but just
  2192.          set number of vertices and binding information here.
  2193.  
  2194.     currentGstate: ptr to the dwbGeoState that should be
  2195.                used for this face. These states are 
  2196.                shared whereever possible but must be
  2197.                set at polygon level cause each face can 
  2198.                have its own texture.
  2199.  
  2200.     vType: just contains the type of face required, flat,gouraud,illuminated
  2201.            or textured.
  2202.  
  2203.  *
  2204.   ======================================================================== */
  2205.  
  2206. static int handleFace(memPtr *ifp, pfNode *parent, pfdGeom *polygon, 
  2207.               dwbGeoState **currentGState,int *vType, pfNode *current)
  2208. {
  2209. /* 
  2210.  * The first few fields in dwbFace and dwbNewFace are the same except
  2211.  * dwbNewFace.pntsize and dwbFace.material which happen to share the same
  2212.  * memory location. Since this field [material] is not used in versions 2.21
  2213.  * and earlier, just load everything into the new structure without any
  2214.  * problems. All the other fields that are used in Version 2.1 have the same
  2215.  * names and memory locations in the later versions.
  2216.  */
  2217.  
  2218. dwbNewFace face;
  2219. int ok=1;
  2220. groupValues *currentGroup = &dwbRoot->currentGroup;
  2221. int vertType;
  2222.  
  2223.   /* read the face record */
  2224.   memRead(&face,sizeof(dwbNewFace),1,ifp);
  2225.   USERFUNCS(DB_FACE, &face, current, parent,ifp);
  2226.  
  2227.   /* ------------------- */
  2228.   /* now handle the face */
  2229.   /* ------------------- */
  2230.  
  2231.   faceBackColor = face.back_color;
  2232.  
  2233.   /* pass on the information up to the DB_POP handler */
  2234.   currentFacePType = face.ptype;
  2235.  
  2236.   /* if this is a bspline then return immediately */
  2237.   if (face.ptype == 3)
  2238.   {
  2239.     SET_COLOR ( polygon,0,face.color, face.packed_color )
  2240.     pfCopyVec4(nextBSplineColor, polygon->colors[0]);
  2241.     return(1);
  2242.   }
  2243.  
  2244.   polygon->numVerts = face.numverts;
  2245.  
  2246.   /* because pfdGeoBuilder doesn't handle lines properly extract those */
  2247.   /* and store them elsewhere */
  2248.  
  2249.   /* get the vertex type */
  2250.   switch ( currentGroup->shading )
  2251.   {
  2252.     case SM_FLAT_NON_LIT:
  2253.         vertType = VT_FLAT_VERTEX;
  2254.         break;
  2255.     case SM_GOURAUD_NON_LIT:
  2256.         if ( face.flags.vertColors )
  2257.             vertType = VT_SHADED_VERTEX;
  2258.         else
  2259.             vertType = VT_FLAT_VERTEX;
  2260.         break;
  2261.     case SM_ILLUMINATED:
  2262.         switch ( currentGroup->binding )
  2263.         {
  2264.             case MB_PER_VERTEX:
  2265.                 if (face.flags.vertColors )
  2266.                     vertType = VT_SHADED_ILLUM_VERTEX;
  2267.                 else
  2268.                     vertType = VT_ILLUM_VERTEX;
  2269.                 break;
  2270.             default:
  2271.                 vertType = VT_ILLUM_VERTEX;
  2272.                 break;
  2273.         }
  2274.         break;
  2275.     default:
  2276.         break;
  2277.   }
  2278.  
  2279.   if (face.texture >= 0)
  2280.   {
  2281.     vertType ^= TEXTURED_VERT;
  2282.     dwbRoot->currentGroup.texture = getDwbTexture(face.texture);
  2283.     /*
  2284.      * Only the extended version supports loading of Detailed texture.
  2285.      * So check for the version and then if this texture is flagged as
  2286.      * a detailed texture, then load the texture.
  2287.      * If the loading was successful, then apply the detail texture
  2288.      * using the texture indices. 
  2289.      */
  2290.     if (extendedVersion && face.detail_tex >= 0) {
  2291.       if (getDwbTexture (face.detail_tex) >= 0) {
  2292.     applyDetailTexture (face.texture, face.detail_tex);
  2293.       }
  2294.     }
  2295.   }
  2296.   else
  2297.     dwbRoot->currentGroup.texture = -1;
  2298.  
  2299.   /*--------------------------------------------------*/
  2300.   /* tell the pfdGeoBuilder polygon how to interpret the */
  2301.   /* data being passed to it. Ie how to bind colors   */
  2302.   /* etc.                                             */
  2303.   /*--------------------------------------------------*/
  2304.   setUpPolygonBindTypes ( polygon,vertType );
  2305.  
  2306.   /*--------------------------------------------------*/
  2307.   /* certain vertex types require 1 color for the     */
  2308.   /* primitive. Assign that color now before we get to*/
  2309.   /* the vertex level.                                */
  2310.   /*--------------------------------------------------*/
  2311.   switch ( vertType )
  2312.   {
  2313.     case VT_FLAT_VERTEX:
  2314.     case VT_FLAT_VERTEX + TEXTURED_VERT:
  2315.     case VT_ILLUM_VERTEX:
  2316.     case VT_ILLUM_VERTEX + TEXTURED_VERT:
  2317.         SET_COLOR ( polygon,0,face.color, face.packed_color )
  2318.         break;
  2319.     default:
  2320.         break;
  2321.   }
  2322.  
  2323.  
  2324.   /* override the group drawstyle */
  2325.   dwbRoot->currentGroup.drawstyle = face.drawstyle;
  2326.  
  2327.   /* get the dwbGeoState for this face */
  2328.   *currentGState = getDwbGeoState ();
  2329.  
  2330.   *vType = vertType;
  2331.  
  2332.   /* ------------------------------------------------------- */
  2333.   /* linestyles are added per face to avoid conflicting with */
  2334.   /* clip regions at group level                             */
  2335.   /* ------------------------------------------------------- */
  2336.  
  2337.   if (face.linestyle > 0)
  2338.   {
  2339.   LineStyle *lineStyle;
  2340.  
  2341.       lineStyle = pfCalloc(1, sizeof(LineStyle),Arena);
  2342.       lineStyle->index = face.linestyle;
  2343.       lineStyle->style = lineStyles[lineStyle->index].style;
  2344.  
  2345.       pfNodeTravFuncs(current,PFTRAV_DRAW,setLineStyleOn,setLineStyleOff);
  2346.       pfNodeTravData(current, PFTRAV_DRAW, (void *) lineStyle);
  2347.   }
  2348.  
  2349.   return(ok);
  2350. }
  2351.  
  2352.  
  2353. /*========================================================================
  2354.  *
  2355.  * FUNCTION     : setUpPolygonBindTypes
  2356.  * IN           : ptr to poly being set up & vert type associated with the
  2357.  *                current polygon.
  2358.  * OUT          : nothing
  2359.  * DESCRIPTION  : tidy up the the convDwbFace() routine by calling this func.
  2360.  *                Set poly bind types for pfdGeoBuilder utilities
  2361.  *
  2362.  *========================================================================*/
  2363.  
  2364.  
  2365. static void setUpPolygonBindTypes ( pfdGeom *polyptr,int vertType )
  2366. {
  2367. int newVertType = vertType;
  2368.  
  2369.   if (vertType & TEXTURED_VERT)
  2370.   {
  2371.     polyptr->tbind = PFGS_PER_VERTEX;
  2372.     newVertType ^= TEXTURED_VERT;
  2373.   }
  2374.   else
  2375.   {
  2376.     polyptr->tbind = PFGS_OFF;
  2377.   }
  2378.  
  2379.   switch (  newVertType )
  2380.   {
  2381.     case VT_FLAT_VERTEX:
  2382.       polyptr->cbind = PFGS_PER_PRIM;     /* build polygon definitions */
  2383.       polyptr->nbind = PFGS_OFF;
  2384.       break;
  2385.     case VT_SHADED_VERTEX:
  2386.       polyptr->cbind = PFGS_PER_VERTEX;
  2387.       polyptr->nbind = PFGS_OFF;
  2388.       break;
  2389.     case VT_ILLUM_VERTEX:
  2390.       polyptr->cbind = PFGS_PER_PRIM;
  2391.       polyptr->nbind = PFGS_PER_VERTEX;
  2392.       break;
  2393.     case VT_SHADED_ILLUM_VERTEX:
  2394.       polyptr->cbind = PFGS_PER_VERTEX; /* old loader did PFGS_PER_PRIM */
  2395.       polyptr->nbind = PFGS_PER_VERTEX;
  2396.       break;
  2397.     default:
  2398.       break;
  2399.   }
  2400.  
  2401. }
  2402.  
  2403.  
  2404.  
  2405.  
  2406.  
  2407.  
  2408.  
  2409. /*========================================================================
  2410.  *
  2411.  * FUNCTION     : getDwbGeoState
  2412.  * IN           : nothing
  2413.  * OUT          : ptr to geostate wrapper
  2414.  * DESCRIPTION  : check geostate stuff & return the 1 which matches current
  2415.  *                group attribs.
  2416.  *
  2417.  *========================================================================*/
  2418.  
  2419. static dwbGeoState *getDwbGeoState ( void )
  2420. {
  2421. dwbGeoState *gstate;
  2422. groupValues *curr = &dwbRoot->currentGroup;
  2423.  
  2424.   if ( dwbRoot->gsList )
  2425.     for ( gstate = dwbRoot->gsList; gstate != NULL; gstate = gstate->next)
  2426.             if (curr->material  == gstate->values.material   &&
  2427.                 curr->binding   == gstate->values.binding    &&
  2428.                 curr->backface  == gstate->values.backface   &&
  2429.                 curr->zbuffer   == gstate->values.zbuffer    &&
  2430.                 curr->drawstyle == gstate->values.drawstyle  &&
  2431.                 curr->alpha     == gstate->values.alpha      &&
  2432.                 curr->texture   == gstate->values.texture  )
  2433.         return ( gstate );
  2434.   
  2435.   /* if we get to this point then a new geoState is needed */
  2436.   gstate = makeDwbGeoState();
  2437.  
  2438.   gstate->next = dwbRoot->gsList;
  2439.   dwbRoot->gsList = gstate;
  2440.  
  2441.   return(gstate);
  2442. }
  2443.  
  2444.  
  2445. /*======================================================================== *
  2446.  * FUNCTION     : makeDwbGeoState
  2447.  * IN           : ptr to geostate wrapper
  2448.  * OUT          : ptr to created dwb geostate wrapper func.
  2449.  * DESCRIPTION  : assign geostate stuff
  2450.  *
  2451.  *========================================================================*/
  2452.  
  2453. static dwbGeoState *makeDwbGeoState ( void )
  2454. {
  2455. dwbGeoState *gstate = NULL;
  2456. groupValues *group = &dwbRoot->currentGroup;
  2457.  
  2458.   gstate = (dwbGeoState *) pfCalloc(1, sizeof(dwbGeoState), Arena);
  2459.  
  2460.   if ( gstate )
  2461.   {
  2462.     gstate->values = *group;
  2463.  
  2464.     /*----------------------------------------------*/
  2465.     /* initialize utility library triangle/geoset   */
  2466.     /* builder                                      */
  2467.     /*----------------------------------------------*/
  2468.     if ( group->drawstyle == DS_OPEN_WIRE || 
  2469.          group->drawstyle == DS_CLOSED_WIRE )
  2470.         gstate->builder     = NULL;
  2471.     else
  2472.         gstate->builder     = pfdNewGeoBldr();
  2473.  
  2474.     /*----------------------------------------------*/
  2475.     /* seperate list of non-solid-filled line polys */
  2476.     /*----------------------------------------------*/
  2477.     gstate->lineList        = NULL;
  2478.  
  2479.     /*----------------------------------------------*/
  2480.     /* also create a performer geostate with the    */
  2481.     /* passed in values.                            */
  2482.     /*----------------------------------------------*/
  2483.     gstate->pfgs = makePfGeoState(gstate);
  2484.  
  2485.     gstate->next = NULL;
  2486.  
  2487.   }
  2488.   return ( gstate );
  2489. }
  2490.  
  2491. typedef struct _DuffTexList
  2492. {
  2493.   char *name;
  2494.   struct _DuffTexList *next;
  2495. } duffTexList;
  2496. static duffTexList *firstDuffTex;
  2497.  
  2498. static int notInDuffTexList( char *str)
  2499. {
  2500. duffTexList *ptr = firstDuffTex;
  2501.  
  2502.   while (ptr)
  2503.   {
  2504.     if (!strcmp(str,ptr->name))
  2505.       return(0);
  2506.     
  2507.     ptr = ptr->next;
  2508.   }
  2509.  
  2510.   /* if you get to here, the name is not in the list */
  2511.   ptr = pfCalloc(1, sizeof(duffTexList),NULL);
  2512.   ptr->name = pfMalloc(strlen(str), NULL);
  2513.   strcpy (ptr->name,str);
  2514.  
  2515.   ptr->next = firstDuffTex;
  2516.   firstDuffTex = ptr;
  2517.  
  2518.   return (1);
  2519. }
  2520.   
  2521.  
  2522. /*========================================================================
  2523.  *
  2524.  * FUNCTION     : getDwbTexture
  2525.  * IN           : texture index into memPtr's texpalette
  2526.  * OUT          : PfTexture table index
  2527.  * DESCRIPTION  : Return Performer texture corresponding to dwb texture
  2528.  *                and create new pfTexture if necessary. Textures are shared
  2529.  *                between .dwb  files by texture file name.
  2530.  *
  2531.  *========================================================================*/
  2532.  
  2533. static int getDwbTexture ( int id )
  2534. {
  2535. int            i;
  2536. dwbTexture     *tex;
  2537. pfTexture      *pfTex;
  2538. pfTexEnv       *pfTev;
  2539. dwbFile        *dwb = dwbRoot;
  2540. float          minf,magf,
  2541.            wrap,wrapS,wrapT,
  2542.            env, r,g,b,a;
  2543. char            path[PF_MAXSTRING];
  2544. int           notFound =0;
  2545.  
  2546.   if (id < 0 )
  2547.     return ( id );
  2548.  
  2549.   /*--------------------------------------------------*/
  2550.   /* If the texture index is valid but NO texture     */
  2551.   /* table was found in the file.Probarbly originated */
  2552.   /* as an early dwb file and treat it as untextured. */
  2553.   /*--------------------------------------------------*/
  2554.   if ( dwb->textureTable == NULL )
  2555.     return ( -1 );
  2556.  
  2557.   if ( id >= dwb->texturesRead )
  2558.     return ( -1 );
  2559.  
  2560.   /* -------------------------------------------- */
  2561.   /* check to see if this file has reference this */
  2562.   /* texture before */
  2563.   /*----------------------------------------------*/
  2564.   if (dwbRoot->pfTexIndex[id] >= 0)
  2565.     return (dwbRoot->pfTexIndex[id]);
  2566.   else if (dwbRoot->pfTexIndex[id] == TEXTURE_NOT_FOUND)
  2567.     return(-1);
  2568.  
  2569.   /* get a local handle to texture table struct       */
  2570.   /*--------------------------------------------------*/
  2571.   tex = &(dwb->textureTable[id]);
  2572.  
  2573.   /*--------------------------------------------------*/
  2574.   /* read tex props from the table.                   */
  2575.   /*--------------------------------------------------*/
  2576.  
  2577.   switch ((int) ((double) tex->tex.minfilter))
  2578.   {
  2579.     case DWB_TX_POINT: minf = PFTEX_POINT; break;
  2580.     case DWB_TX_BILINEAR: minf = PFTEX_BILINEAR; break;
  2581.  
  2582. #ifdef IRISGL
  2583.     /* These guys are not defined in OpenGL */
  2584.  
  2585.     case DWB_TX_BILINEAR_LEQUAL: minf = PFTEX_BILINEAR_LEQUAL; break;
  2586.     case DWB_TX_BILINEAR_GEQUAL: minf = PFTEX_BILINEAR_GEQUAL; break;
  2587. #endif /* end GL type */
  2588.  
  2589.     case DWB_TX_BICUBIC: minf = PFTEX_BICUBIC; break;
  2590.     case DWB_TX_MIPMAP_POINT: minf = PFTEX_MIPMAP_POINT; break;
  2591.     case DWB_TX_MIPMAP_LINEAR: minf = PFTEX_MIPMAP_LINEAR; break;
  2592.     case DWB_TX_MIPMAP_BILINEAR: minf = PFTEX_MIPMAP_BILINEAR; break;
  2593.     case DWB_TX_MIPMAP_TRILINEAR: minf = PFTEX_MIPMAP_TRILINEAR; break;
  2594.     default:
  2595.       fprintf (stderr, "loadDwb: Unknown minFilter for %s\n", tex->name);
  2596.       minf = PFTEX_BILINEAR;
  2597.     break;
  2598.   }
  2599.  
  2600.   switch ((int) ((double) tex->tex.magfilter))
  2601.   {
  2602.     case DWB_TX_POINT: magf = PFTEX_POINT; break;
  2603.     case DWB_TX_BILINEAR: magf = PFTEX_BILINEAR; break;
  2604.  
  2605. #ifdef IRISGL
  2606.     /* These guys are not defined in OpenGL */
  2607.  
  2608.     case DWB_TX_BILINEAR_LEQUAL: magf = PFTEX_BILINEAR_LEQUAL; break;
  2609.     case DWB_TX_BILINEAR_GEQUAL: magf = PFTEX_BILINEAR_GEQUAL; break;
  2610. #endif /* end GL type */
  2611.  
  2612.     case DWB_TX_BICUBIC: magf = PFTEX_BICUBIC; break;
  2613.     case DWB_TX_SHARPEN: magf = PFTEX_SHARPEN; break;
  2614.     case DWB_TX_ADD_DETAIL: magf = PFTEX_ADD_DETAIL; break;
  2615.     case DWB_TX_MODULATE_DETAIL: magf = PFTEX_MODULATE_DETAIL; break;
  2616.     default:
  2617.       fprintf (stderr, "loadDwb: Unknown magFilter for %s\n", tex->name);
  2618.       magf = PFTEX_BILINEAR;
  2619.     break;
  2620.   }
  2621.  
  2622.   switch ((int) ((double) tex->tex.wrap))
  2623.   {
  2624.     case DWB_TX_REPEAT: wrap = PFTEX_REPEAT; break;
  2625.     case DWB_TX_CLAMP: wrap = PFTEX_CLAMP; break;
  2626.     case DWB_TX_SELECT: wrap = PFTEX_SELECT; break;
  2627.     default:
  2628.       fprintf (stderr, "loadDwb: Unknown texture wrap for %s\n", tex->name);
  2629.       wrap = PFTEX_REPEAT;
  2630.     break;
  2631.   }
  2632.  
  2633.   switch ((int) ((double) tex->tex.wraps))
  2634.   {
  2635.     case DWB_TX_REPEAT: wrapS = PFTEX_REPEAT; break;
  2636.     case DWB_TX_CLAMP: wrapS = PFTEX_CLAMP; break;
  2637.     case DWB_TX_SELECT: wrapS = PFTEX_SELECT; break;
  2638.     default:
  2639.       fprintf (stderr, "loadDwb: Unknown texture wrapS for %s\n", tex->name);
  2640.       wrapS = PFTEX_REPEAT;
  2641.     break;
  2642.   }
  2643.  
  2644.   switch ((int) ((double) tex->tex.wrapt))
  2645.   {
  2646.     case DWB_TX_REPEAT: wrapT = PFTEX_REPEAT; break;
  2647.     case DWB_TX_CLAMP: wrapT = PFTEX_CLAMP; break;
  2648.     case DWB_TX_SELECT: wrapT = PFTEX_SELECT; break;
  2649.     default:
  2650.       fprintf (stderr, "loadDwb: Unknown texture wrapT for %s\n", tex->name);
  2651.       wrapT = PFTEX_REPEAT;
  2652.     break;
  2653.   }
  2654.  
  2655.   switch ((int) ((double) tex->tex.envtype))
  2656.   {
  2657.     case DWB_TV_MODULATE: env = PFTE_MODULATE; break;
  2658.     case DWB_TV_BLEND: env = PFTE_BLEND; break;
  2659.     case DWB_TV_DECAL: env = PFTE_DECAL; break;
  2660. #ifdef IRISGL
  2661.     case DWB_TV_ALPHA: env = PFTE_ALPHA; break;
  2662. #endif /* end GL type */
  2663.     default:
  2664.       fprintf (stderr, "loadDwb: Unknown texEnv for %s\n", tex->name);
  2665.       env = PFTE_MODULATE;
  2666.     break;
  2667.   }
  2668.  
  2669.   if (extendedVersion) {
  2670.     r = tex->tex.envcolor[0];
  2671.     g = tex->tex.envcolor[1];
  2672.     b = tex->tex.envcolor[2];
  2673.     a = tex->tex.envcolor[3];
  2674.   }
  2675.  
  2676.   /*--------------------------------------------------*/
  2677.   /* See if we can find texture file                  */
  2678.   /*--------------------------------------------------*/
  2679.   if (!pfFindFile(tex->name, path, R_OK))
  2680.   {
  2681.       pfNotify(PFNFY_WARN,PFNFY_RESOURCE,
  2682.             "LoadDwb: Could not find texture \"%s\"", tex->name);
  2683.  
  2684.       dwbRoot->pfTexIndex[id] = TEXTURE_NOT_FOUND;  
  2685.  
  2686.     return(-1);
  2687.  
  2688.   }
  2689.  
  2690.   /*--------------------------------------------------*/
  2691.   /* See if texture was already loaded by another file*/
  2692.   /*--------------------------------------------------*/
  2693.   for (i = 0; i < sharedTexCount; i++)
  2694.   {
  2695.       const char *str =  pfGetTexName(sharedTexList[i]);
  2696.       if (!str)
  2697.           continue;
  2698.  
  2699.       if(!strcmp(path, str))
  2700.       {
  2701.           dwbRoot->pfTexIndex[id] = i;
  2702.           return (i);
  2703.       }
  2704.   }
  2705.  
  2706.   /*--------------------------------------------------*/
  2707.   /* Could not share texture ...create a new pfTexture*/
  2708.   /*--------------------------------------------------*/
  2709.   pfTex = pfNewTex(Arena);
  2710.  
  2711.   /*--------------------------------------------------*/
  2712.   /* load it..                                        */
  2713.   /*--------------------------------------------------*/
  2714. #ifndef ENCRYPT
  2715.  
  2716. #ifdef __ESCENE__
  2717.   if (encrypted)
  2718.       mypfLoadTexFile(pfTex, path);
  2719.   else
  2720.     pfLoadTexFile(pfTex,path);
  2721. #else
  2722.     pfLoadTexFile(pfTex,path);
  2723. #endif
  2724.  
  2725. #else
  2726.     mypfLoadTexFile(pfTex, path);
  2727.  
  2728. #endif
  2729.  
  2730.   if(pfGetNotifyLevel() >= PFNFY_INFO)
  2731.   {
  2732.   int comp, x, y, z;
  2733.   unsigned int *image;
  2734.     pfGetTexImage(pfTex, &image, &comp, &x, &y, &z);
  2735.  
  2736.     /* don't shorten name so user can see full path */
  2737.     /* could resolve some path problems as dwb stores full path names */
  2738.  
  2739.     pfNotify(PFNFY_INFO,PFNFY_RESOURCE, 
  2740.            "Loaded texture %s:\n\t %d component, (%d, %d, %d)\n",
  2741.                     path, comp, x, y, z);
  2742.   }
  2743.  
  2744.   pfTexFilter(pfTex, PFTEX_MINFILTER, minf );
  2745.   pfTexFilter(pfTex, PFTEX_MAGFILTER, magf );
  2746.    
  2747.   if (GfxType & GFX_REALITY)
  2748.   {
  2749.     int comp,foo;
  2750.  
  2751.     pfGetTexImage(pfTex, (unsigned int **)&foo, &comp, &foo, &foo, &foo);
  2752.  
  2753.     /* Assume alpha texture is a template so sharpen alpha */
  2754.     if(comp == 2 || comp == 4)
  2755.       pfTexFilter(pfTex, PFTEX_MAGFILTER_ALPHA, PFTEX_SHARPEN);
  2756.   }
  2757.  
  2758.   pfTexRepeat ( pfTex, PFTEX_WRAP, wrap );
  2759.   pfTexRepeat ( pfTex, PFTEX_WRAP_S, wrapS );
  2760.   pfTexRepeat ( pfTex, PFTEX_WRAP_T, wrapT );
  2761.  
  2762. #ifdef IRISGL
  2763.   if (env == PFTE_DECAL || env == PFTE_ALPHA || env == PFTE_MODULATE) 
  2764. #else
  2765.   /* Theres's no PFTE_ALPHA in OpenGL */
  2766.  
  2767.   if (env == PFTE_DECAL || env == PFTE_MODULATE) 
  2768. #endif /* end GL type */
  2769.   {
  2770.     pfTev = pfNewTEnv (Arena);
  2771.     pfTEnvMode (pfTev, env);
  2772.   }
  2773.   else if (env == PFTE_BLEND) {
  2774.     if (! extendedVersion) {
  2775.       fprintf (stderr, 
  2776.       "LoadDwb: Older version does not support BLENDed Textures\n"
  2777.       "         Defaulting to MODULATEd textures\n");
  2778.       pfTev = defTEnv;
  2779.     }
  2780.     else {
  2781.       pfTev = pfNewTEnv (Arena);
  2782.       pfTEnvMode (pfTev, env);
  2783.       pfTEnvBlendColor (pfTev, r, g, b, a);
  2784.     }
  2785.   }
  2786.   else {
  2787.     fprintf (stderr,
  2788.     "LoadDwb: Unknown texture environment for \"%s\"\n", tex->name);
  2789.     pfTev = defTEnv;
  2790.   }
  2791.  
  2792.   /*
  2793.    * The flags in the extended structure will definitely be zero, if the
  2794.    * file is a older version, because all the bytes past the 96th are 
  2795.    * bzero()ed in handleTexture.
  2796.    */
  2797.   if (extendedVersion) {
  2798.     if (tex->tex.flags.component_select) {
  2799.     float pfcomp;
  2800.  
  2801.       fprintf (stderr, "compselect: %d\n", tex->tex.component_select);
  2802.       switch ((int) ((double) tex->tex.component_select))
  2803.       {
  2804.     case DWB_TV_I_GETS_R: pfcomp = PFTE_COMP_I_GETS_R; break;
  2805.     case DWB_TV_I_GETS_G: pfcomp = PFTE_COMP_I_GETS_G; break;
  2806.     case DWB_TV_I_GETS_B: pfcomp = PFTE_COMP_I_GETS_B; break;
  2807.     case DWB_TV_I_GETS_A: pfcomp = PFTE_COMP_I_GETS_A; break;
  2808. #ifdef IRISGL
  2809.         /*
  2810.      * These guys are not in OpenGL
  2811.      */
  2812.  
  2813.     case DWB_TV_IA_GETS_RG: pfcomp = PFTE_COMP_IA_GETS_RG; break;
  2814.     case DWB_TV_IA_GETS_BA: pfcomp = PFTE_COMP_IA_GETS_BA; break;
  2815. #endif /* end GL type */
  2816.         case DWB_TV_I_GETS_I: pfcomp = PFTE_COMP_I_GETS_I; break;
  2817.       }
  2818.  
  2819.       pfTEnvComponent (pfTev, pfcomp);
  2820.     }
  2821.  
  2822.     if (tex->tex.flags.magfilter_split && (GfxType & GFX_REALITY)) 
  2823.     {
  2824.     float malpha, mcolor;
  2825.  
  2826.       switch ((int) ((double) tex->tex.magfilter_alpha))
  2827.       {
  2828.     case DWB_TX_POINT: malpha = PFTEX_POINT; break;
  2829.     case DWB_TX_BILINEAR: malpha = PFTEX_BILINEAR; break;
  2830.  
  2831. #ifdef IRISGL
  2832.         /* these guys are not defined in OpenGL */
  2833.  
  2834.     case DWB_TX_BILINEAR_LEQUAL: malpha = PFTEX_BILINEAR_LEQUAL; break;
  2835.     case DWB_TX_BILINEAR_GEQUAL: malpha = PFTEX_BILINEAR_GEQUAL; break;
  2836. #endif /* end GL type */
  2837.  
  2838.     case DWB_TX_BICUBIC: malpha = PFTEX_BICUBIC; break;
  2839.     case DWB_TX_SHARPEN: malpha = PFTEX_SHARPEN; break;
  2840.     case DWB_TX_ADD_DETAIL: malpha = PFTEX_ADD_DETAIL; break;
  2841.     case DWB_TX_MODULATE_DETAIL: malpha = PFTEX_MODULATE_DETAIL; break;
  2842.     default:
  2843.       fprintf (stderr, "loadDwb: Unknown alphaFilter for %s\n", tex->name);
  2844.       malpha = PFTEX_POINT;
  2845.     break;
  2846.       }
  2847.  
  2848.       pfTexFilter (pfTex, PFTEX_MAGFILTER_ALPHA, malpha);
  2849.  
  2850.       switch ((int) ((double) tex->tex.magfilter_color))
  2851.       {
  2852.     case DWB_TX_POINT: mcolor = PFTEX_POINT; break;
  2853.     case DWB_TX_BILINEAR: mcolor = PFTEX_BILINEAR; break;
  2854.  
  2855. #ifdef IRISGL
  2856.     /* these guys are not defined in OpenGL */
  2857.  
  2858.     case DWB_TX_BILINEAR_LEQUAL: mcolor = PFTEX_BILINEAR_LEQUAL; break;
  2859.     case DWB_TX_BILINEAR_GEQUAL: mcolor = PFTEX_BILINEAR_GEQUAL; break;
  2860. #endif /* end GL type */
  2861.  
  2862.     case DWB_TX_BICUBIC: mcolor = PFTEX_BICUBIC; break;
  2863.     case DWB_TX_SHARPEN: mcolor = PFTEX_SHARPEN; break;
  2864.     case DWB_TX_ADD_DETAIL: mcolor = PFTEX_ADD_DETAIL; break;
  2865.     case DWB_TX_MODULATE_DETAIL: mcolor = PFTEX_MODULATE_DETAIL; break;
  2866.     default:
  2867.       fprintf (stderr, "loadDwb: Unknown colorFilter for %s\n", tex->name);
  2868.       mcolor = PFTEX_POINT;
  2869.     break;
  2870.       }
  2871.  
  2872.       pfTexFilter (pfTex, PFTEX_MAGFILTER_COLOR, mcolor);
  2873.     }
  2874.  
  2875.     if (tex->tex.flags.internal && (GfxType & GFX_REALITY)) 
  2876.     {
  2877.     float internal;
  2878.       
  2879.       switch ((int) ((double) tex->tex.internal))
  2880.       {
  2881.     case DWB_TX_I_12A_4: internal = PFTEX_I_12A_4; break;
  2882.     case DWB_TX_IA_8: internal = PFTEX_IA_8; break;
  2883.     case DWB_TX_RGB_5: internal = PFTEX_RGB_5; break;
  2884.     case DWB_TX_RGBA_4: internal = PFTEX_RGBA_4; break;
  2885.     case DWB_TX_IA_12: internal = PFTEX_IA_12; break;
  2886.     case DWB_TX_RGBA_8: internal = PFTEX_RGBA_8; break;
  2887.     case DWB_TX_RGBA_12: internal = PFTEX_RGBA_12; break;
  2888.     case DWB_TX_RGB_12: internal = PFTEX_RGB_12; break;
  2889.     case DWB_TX_I_16: internal = PFTEX_I_16; break;
  2890.     default:
  2891.       fprintf (stderr, "loadDwb: Unknown internal format for %s\n", 
  2892.                tex->name);
  2893.       internal = PFTEX_RGBA_4;
  2894.     break;
  2895.       }
  2896.  
  2897.       pfTexFormat (pfTex, PFTEX_INTERNAL_FORMAT, internal);
  2898.     }
  2899.  
  2900.     if (tex->tex.flags.external && (GfxType & GFX_REALITY)) 
  2901.     {
  2902.     float ext;
  2903.  
  2904.       switch ((int) ((double) tex->tex.external))
  2905.       {
  2906.     case DWB_TX_PACK_8: ext = PFTEX_PACK_8; break;
  2907.     case DWB_TX_PACK_16: ext = PFTEX_PACK_16; break;
  2908.     /*
  2909.      * Performer doesn't understand DWB_TX_PIXMODE
  2910.      */
  2911.     default:
  2912.       fprintf (stderr, "loadDwb: Unknown external format for %s\n",
  2913.                        tex->name);
  2914.     break;
  2915.       }
  2916.  
  2917.       pfTexFormat (pfTex, PFTEX_EXTERNAL_FORMAT, ext);
  2918.     }
  2919.  
  2920.     /*
  2921.      * Just make sure that the mag and min filters are not using MIPMAP
  2922.      * filters when this flag [FAST_DEFINE] is set. The other requirement
  2923.      * is that the texture size should be a multiple of 2, as given in the
  2924.      * texdef2 man pages.
  2925.      */
  2926.  
  2927. #ifdef IRISGL
  2928.     if (tex->tex.flags.fast_define) {
  2929.         pfTexFormat (pfTex, PFTEX_FAST_DEFINE, PF_ON); 
  2930.     }
  2931. #else
  2932.   /* OpenGL doensn't support PFTEX_FAST_DEFINE texture format */
  2933.   /* XXX Do the right thing here */
  2934. #endif /* end GL type */
  2935.  
  2936.     if (tex->tex.flags.mipmap_filter) {
  2937.       fprintf (stderr, 
  2938.       "LoadDwb: Mipmap filters are not supported currently\n");
  2939.       /*
  2940.        * There's no equivalent call for 
  2941.        * texdef (...TX_MIPMAP_FILTER_KERNEL, ...)
  2942.        * in Performer. So just skip it for now.
  2943.        */
  2944.     }
  2945.  
  2946.     if (tex->tex.flags.bicubic_filter) {
  2947.       fprintf (stderr, 
  2948.       "LoadDwb: Bicubic Filters are not supported currently\n");
  2949.       /*
  2950.        * Same reason as above.
  2951.        */
  2952.     }
  2953.  
  2954.     if (tex->tex.flags.control_points) {
  2955.     int splineType = -1;
  2956.     pfVec2 *points = (pfVec2 *) tex->tex.control_points;
  2957.     float clamp = tex->tex.control_clamp;
  2958.  
  2959.       if (magf == PFTEX_SHARPEN) 
  2960.     splineType = PFTEX_SHARPEN_SPLINE;
  2961.       else if (magf == PFTEX_MODULATE_DETAIL || magf == PFTEX_ADD_DETAIL)
  2962.     splineType = PFTEX_DETAIL_SPLINE;
  2963.       else {
  2964.     fprintf (stderr, 
  2965.         "LoadDwb: Unable to determine filter spline for Mag filter\n");
  2966.       }
  2967.  
  2968.       if (splineType != -1)
  2969.     pfTexSpline (pfTex, splineType, points, clamp);
  2970.     }
  2971.  
  2972.     /*
  2973.      * Performer does not have the equivalent of TX_TILE.
  2974.      * Detail texture is handled in handleFace()
  2975.      */
  2976.   }
  2977.  
  2978.   sharedTexList[sharedTexCount] = pfTex;
  2979.   sharedTevList[sharedTexCount] = pfTev;
  2980.   dwbRoot->pfTexIndex[id] = sharedTexCount;
  2981.   sharedTexCount++;
  2982.  
  2983.   return (sharedTexCount-1);
  2984. }
  2985.  
  2986.  
  2987. /*========================================================================
  2988.  *
  2989.  * FUNCTION     : applyDetailTexture
  2990.  * IN           : ids of the main and detail texture
  2991.  * OUT          : nothing
  2992.  * DESCRIPTION  : uses pfTexIndex to index into dwbRoot->textureTable and
  2993.  *                applies the detail texture
  2994.  *========================================================================*/
  2995.  
  2996. static int applyDetailTexture (short texture, short detail)
  2997. {
  2998.     /*
  2999.      * At this point of time, we already know that these textures exist
  3000.      * and have been loaded by getDwbTexture(). So just get the pfTexture
  3001.      * structures by mapping the indices and then apply the Detail
  3002.      * texture.
  3003.      */
  3004.  
  3005.     pfTexture *tex, *det;
  3006.     dwbTexture *texInfo = &(dwbRoot->textureTable[texture]);
  3007.     dwbTexture *detInfo = &(dwbRoot->textureTable[detail]);
  3008.     float j,k,m,n,s;
  3009.  
  3010.   tex = sharedTexList[dwbRoot->pfTexIndex[texture]];
  3011.   det = sharedTexList[dwbRoot->pfTexIndex[detail]];
  3012.  
  3013.   pfTexDetail (tex, PFTEX_DEFAULT, det);
  3014.  
  3015.   j = detInfo->tex.detail[0],
  3016.   k = detInfo->tex.detail[1],
  3017.   m = detInfo->tex.detail[2],
  3018.   n = detInfo->tex.detail[3],
  3019.   s = detInfo->tex.detail[4]; 
  3020.  
  3021.   pfDetailTexTile (det, j, k, m, n, s);
  3022.  
  3023.   return 1;
  3024. }
  3025.  
  3026. /*========================================================================
  3027.  *
  3028.  * FUNCTION     : makePfGeoState
  3029.  * IN           : ptr to a intermediary dwb-geostate struct
  3030.  * OUT          : ptr to pfGeoState
  3031.  * DESCRIPTION  : make a performer geostate from the passed info.
  3032.  *
  3033.  *========================================================================*/
  3034.  
  3035. static pfGeoState *makePfGeoState ( dwbGeoState *gstate )
  3036. {
  3037. pfMaterial     *mtl;
  3038. pfGeoState     *pfGState;
  3039. float          alpha;
  3040. groupValues    *vals = &gstate->values;
  3041.  
  3042.  
  3043.   pfGState = pfNewGState(Arena);
  3044.  
  3045.   if (vals->texture >= 0)
  3046.   {
  3047.     unsigned int   *image;
  3048.     int             comp, sx, sy, sz;
  3049.  
  3050.     /* Assume alpha texture requires afunction */
  3051.     pfGetTexImage(sharedTexList[vals->texture], &image, &comp, 
  3052.                   &sx, &sy, &sz);
  3053.  
  3054.     if (comp == 2 || comp == 4)
  3055.     {
  3056.       /* Use multisample transparency if possible */
  3057.       if (GfxType & GFX_MULTISAMPLE)
  3058.       {
  3059.         pfGStateMode(pfGState, PFSTATE_ALPHAFUNC, PFAF_GEQUAL);
  3060.         pfGStateVal(pfGState, PFSTATE_ALPHAREF, 3.0f/255.0f);
  3061.         pfGStateMode(pfGState, PFSTATE_TRANSPARENCY, PFTR_ON);
  3062.       }
  3063.       else
  3064.       {
  3065.         pfGStateMode(pfGState, PFSTATE_ALPHAFUNC, PFAF_GREATER);
  3066.         pfGStateVal(pfGState, PFSTATE_ALPHAREF, 70.0f/255.0f);
  3067.       }
  3068.     }
  3069.  
  3070.     pfGStateAttr(pfGState, PFSTATE_TEXTURE, 
  3071.                  sharedTexList[vals->texture]);
  3072.     pfGStateAttr(pfGState, PFSTATE_TEXENV, 
  3073.                  sharedTevList[vals->texture]);
  3074.  
  3075.     pfGStateMode(pfGState, PFSTATE_ENTEXTURE, PF_ON);
  3076.  
  3077.   }
  3078.   else
  3079.   {
  3080.     pfGStateMode(pfGState, PFSTATE_ENTEXTURE, PF_OFF); 
  3081.   }
  3082.  
  3083.   mtl = getPfMaterial(gstate);
  3084.  
  3085.   if(mtl != NULL)
  3086.   {
  3087.     pfGStateAttr ( pfGState, PFSTATE_FRONTMTL, mtl );
  3088.  
  3089.     alpha = pfGetMtlAlpha(mtl);
  3090.     if (alpha < (1.0 - (1.0/256.0)) )
  3091.         pfGStateMode(pfGState, PFSTATE_TRANSPARENCY, PFTR_ON);
  3092.  
  3093.     /* Lighting should be enabled by default ?? */
  3094.     pfGStateMode(pfGState, PFSTATE_ENLIGHTING, PF_ON);
  3095.   }
  3096.   else
  3097.     pfGStateMode(pfGState, PFSTATE_ENLIGHTING, PF_OFF);
  3098.  
  3099.   /* Backface culling should be on by default */
  3100.   pfGStateMode(pfGState, PFSTATE_CULLFACE, (vals->backface)?PF_ON:PF_OFF);
  3101.  
  3102.   /*--------------------------------------------------*/
  3103.   /* check for transparent (non-lit) groups           */
  3104.   /*--------------------------------------------------*/
  3105.   if ( vals->alpha < (1.0 - (1.0/256.0)) && vals->material == -1 )
  3106.       pfGStateMode(pfGState, PFSTATE_TRANSPARENCY, PFTR_ON);
  3107.  
  3108.   /*--------------------------------------------------*/
  3109.   /* check for non-solid geosets.                     */
  3110.   /*--------------------------------------------------*/
  3111.   if ( vals->drawstyle == DS_CLOSED_WIRE )
  3112.       pfGStateMode(pfGState, PFSTATE_ENWIREFRAME, PFTR_ON);
  3113.  
  3114.     return ( pfGState );
  3115. }
  3116.  
  3117. /*========================================================================
  3118.  *
  3119.  * FUNCTION     : getPfMaterial
  3120.  * IN           : ptr to a dwb geostate
  3121.  * OUT          : ptr to a Performer Material
  3122.  * DESCRIPTION  : Return Performer material corresponding to Dwb material
  3123.  *                and create new pfMaterial if necessary. This routine uses
  3124.  *                lmcolor mode LMC_AD to reduce number of materials needed.
  3125.  *
  3126.  *========================================================================*/
  3127.  
  3128. static pfMaterial *getPfMaterial ( dwbGeoState *gs )
  3129. {
  3130.     pfMaterial          *pfm;
  3131.     int                 mid;
  3132.  
  3133.     if ( !gs->values.binding  )     /* No material lighting */
  3134.         return ( NULL );
  3135.  
  3136.  
  3137.     if ( dwbRoot->materialTable == NULL ) /* no material table read  */
  3138.         gs->values.material = -1;         /* default to std material */
  3139.  
  3140.     mid = gs->values.material + 1;     /* + 1 for material == -1 */
  3141.  
  3142.     if( dwbRoot->materials[mid] == NULL)
  3143.     {
  3144.  
  3145.         pfm = dwbRoot->materials[mid] = pfNewMtl(Arena);
  3146.  
  3147.         if ( gs->values.binding == MB_PER_GROUP )
  3148.             pfMtlColorMode(pfm, PFMTL_FRONT, PFMTL_CMODE_COLOR);
  3149.         else /* bind per primitive */
  3150.             pfMtlColorMode(pfm, PFMTL_FRONT, PFMTL_CMODE_AD);
  3151.  
  3152.         if(gs->values.material >= 0)
  3153.         {
  3154.             dwbMaterial         *dwbmat;
  3155.  
  3156.             dwbmat = &(dwbRoot->materialTable[gs->values.material].mat );
  3157.  
  3158.             if ( gs->values.binding == MB_PER_GROUP )
  3159.                 pfMtlColor(pfm, PFMTL_DIFFUSE,  dwbmat->diffuse[0],
  3160.                                                 dwbmat->diffuse[1],
  3161.                                                 dwbmat->diffuse[2]);
  3162.  
  3163.             pfMtlColor(pfm, PFMTL_AMBIENT,  dwbmat->ambient[0],
  3164.                                             dwbmat->ambient[1],
  3165.                                             dwbmat->ambient[2]);
  3166.  
  3167.  
  3168.             pfMtlColor(pfm, PFMTL_SPECULAR, dwbmat->specular[0],
  3169.                                             dwbmat->specular[1],
  3170.                                             dwbmat->specular[2]);
  3171.  
  3172.             pfMtlColor(pfm, PFMTL_EMISSION, dwbmat->emissive[0],
  3173.                                             dwbmat->emissive[1],
  3174.                                             dwbmat->emissive[2]);
  3175.  
  3176.             pfMtlShininess(pfm, dwbmat->shininess);
  3177.  
  3178.             pfMtlAlpha(pfm, dwbmat->alpha);
  3179.         }
  3180.         else
  3181.         {
  3182.             /* Use GL default ambient of .2 */
  3183.             pfMtlColor(pfm, PFMTL_AMBIENT, .2, .2, .2);
  3184.  
  3185.             /* Use rest of GL defaults which are pfMaterial defaults. */
  3186.         }
  3187.     }
  3188.  
  3189.     return ( dwbRoot->materials[mid] );
  3190. }
  3191.  
  3192.  
  3193.  
  3194.  
  3195.  
  3196.  
  3197.  
  3198. /*========================================================================
  3199.  *
  3200.  * FUNCTION     : unPackRGBA
  3201.  * IN           : pached color & ptrs to rgb
  3202.  * OUT          : rgba as 4 shorts
  3203.  * DESCRIPTION  : unpack a cpack color definition into constituent rgb values.
  3204.  *
  3205.  *========================================================================*/
  3206.  
  3207. void unPackRGBA ( unsigned int pcolor,float *rgba )
  3208. {
  3209.     short sr = (pcolor << 24) >> 24;
  3210.     short sg = (((pcolor >> 8) << 24) >> 24);
  3211.     short sb = (pcolor << 8) >> 24;
  3212.     short sa = (pcolor >> 24);
  3213.  
  3214.     *(rgba)     = ((float)sr) / 255.0;
  3215.     *(rgba + 1) = ((float)sg) / 255.0;
  3216.     *(rgba + 2) = ((float)sb) / 255.0;
  3217.     *(rgba + 3) = ((float)sa) / 255.0;
  3218. }
  3219.  
  3220.  
  3221.  
  3222.  
  3223.  
  3224.  
  3225. /*========================================================================
  3226.  * Read a Packed vertex record and store it into the supplied polygon record
  3227.  *
  3228.  *========================================================================*/
  3229. static int handlePackedVertex(memPtr *ifp, int vertType, pfdGeom *polygon, short length)
  3230. {
  3231. int loop;
  3232. dwbPackedVertex vert;
  3233. float tmpVert[3];
  3234. float norm[3];
  3235. int vt;
  3236.  
  3237.   /* bsplines will not have any polygon length - all information */
  3238.   /* is given later in a special record */
  3239.   if (length != sizeof(dwbVertex) * polygon->numVerts)
  3240.   {
  3241.     memSeek(ifp,length,SEEK_CUR);
  3242.     return(1);
  3243.   }
  3244.  
  3245.   for (loop=0; loop< polygon->numVerts; loop++)
  3246.   {
  3247.     memRead(&vert,sizeof(dwbPackedVertex),1,ifp);
  3248.     USERFUNCS (DB_PACKED_VERTEX, &vert, (pfNode *) NULL, (pfNode *) NULL, ifp);
  3249.  
  3250.     copyNyup(tmpVert,vert.coords,dwbRoot->unitChange);
  3251.     copyNyup(norm,vert.normal,1.0);
  3252.     
  3253.     vt = vertType;
  3254.  
  3255.     if (vt & TEXTURED_VERT)
  3256.     {
  3257.       pfCopyVec2 ( polygon->texCoords[loop],vert.tex_coords );
  3258.       vt -= TEXTURED_VERT;
  3259.     }
  3260.  
  3261.     switch( vt )
  3262.     {
  3263.       case VT_FLAT_VERTEX:
  3264.         pfCopyVec3 ( polygon->coords[loop],tmpVert );
  3265.       break;
  3266.  
  3267.       case VT_SHADED_VERTEX:
  3268.         pfCopyVec3 ( polygon->coords[loop],tmpVert );
  3269.         unPackRGBA ( vert.packed_color,polygon->colors[loop] );
  3270.       break;
  3271.       case VT_ILLUM_VERTEX:
  3272.         pfCopyVec3 ( polygon->coords[loop],tmpVert );
  3273.         pfCopyVec3 ( polygon->norms[loop],norm );
  3274.       break;
  3275.       case VT_SHADED_ILLUM_VERTEX:
  3276.         pfCopyVec3 ( polygon->coords[loop],tmpVert );
  3277.         pfCopyVec3 ( polygon->norms[loop],norm );
  3278.         unPackRGBA ( vert.packed_color,polygon->colors[loop] );
  3279.       break;
  3280.     }
  3281.   }
  3282.   return(1);
  3283. }
  3284.  
  3285.  
  3286.  
  3287. /*========================================================================
  3288.  * Read a vertex record and store it into the supplied polygon record
  3289.  *
  3290.  *========================================================================*/
  3291. static int handleVertex(memPtr *ifp, int vertType, pfdGeom *polygon, short length)
  3292. {
  3293. int loop;
  3294. dwbVertex vert;
  3295. float tmpVert[3];
  3296. float norm[3];
  3297. int vt;
  3298.  
  3299.   /* bsplines will not have any polygon length - all information */
  3300.   /* is given later in a special record */
  3301.   if (length != sizeof(dwbVertex) * polygon->numVerts)
  3302.   {
  3303.     memSeek(ifp,length,SEEK_CUR);
  3304.     return(1);
  3305.   }
  3306.  
  3307.   for (loop=0; loop< polygon->numVerts; loop++)
  3308.   {
  3309.     memRead(&vert,sizeof(dwbVertex),1,ifp);
  3310.     USERFUNCS (DB_VERTEX, &vert, (pfNode *) NULL, (pfNode *) NULL, ifp);
  3311.  
  3312.     copyNyup(tmpVert,vert.coords,dwbRoot->unitChange);
  3313.     copyNyup(norm,vert.normal,1.0);
  3314.     
  3315.     vt = vertType;
  3316.  
  3317.     if (vt & TEXTURED_VERT)
  3318.     {
  3319.       pfCopyVec2 ( polygon->texCoords[loop],vert.tex_coords );
  3320.       vt -= TEXTURED_VERT;
  3321.     }
  3322.  
  3323.     switch( vt )
  3324.     {
  3325.       case VT_FLAT_VERTEX:
  3326.         pfCopyVec3 ( polygon->coords[loop],tmpVert );
  3327.       break;
  3328.  
  3329.       case VT_SHADED_VERTEX:
  3330.         pfCopyVec3 ( polygon->coords[loop],tmpVert );
  3331.         pfCopyVec3 ( polygon->colors[loop],dwbRoot->colorTable[vert.color] );
  3332.         polygon->colors[loop][3] = dwbRoot->currentGroup.alpha;
  3333.       break;
  3334.       case VT_ILLUM_VERTEX:
  3335.         pfCopyVec3 ( polygon->coords[loop],tmpVert );
  3336.         pfCopyVec3 ( polygon->norms[loop],norm );
  3337.       break;
  3338.       case VT_SHADED_ILLUM_VERTEX:
  3339.         pfCopyVec3 ( polygon->coords[loop],tmpVert );
  3340.         pfCopyVec3 ( polygon->norms[loop],norm );
  3341.         pfCopyVec3 ( polygon->colors[loop],dwbRoot->colorTable[vert.color] );
  3342.         polygon->colors[loop][3] = dwbRoot->currentGroup.alpha;
  3343.       break;
  3344.     }
  3345.   }
  3346.   return(1);
  3347. }
  3348.  
  3349.  
  3350.  
  3351.  
  3352.  
  3353.  
  3354.  
  3355. /*========================================================================
  3356.  * Add a line to the supplied dwbGeoState
  3357.  *
  3358.  *========================================================================*/
  3359.  
  3360. static void addLineToGeoState( dwbGeoState *gstate, pfdGeom *polygon, 
  3361.                                int drawStyle)
  3362. {
  3363. myLines *newPoly;
  3364.  
  3365.   /* need to create a new polygon structure and add that to the line list */
  3366.   newPoly = pfCalloc(1,sizeof(myLines),NULL);
  3367.  
  3368.  
  3369.   if (polygon->numVerts > 255)
  3370.     newPoly->numVerts = 255;
  3371.   else
  3372.     newPoly->numVerts = polygon->numVerts;
  3373.  
  3374.  
  3375.   newPoly->cbind = polygon->cbind;
  3376.  
  3377.   /* copy the existing polygons values */
  3378.   memcpy(newPoly->coords,polygon->coords,sizeof(pfVec3) * newPoly->numVerts);
  3379.   memcpy(newPoly->colors,polygon->colors,sizeof(pfVec4) * newPoly->numVerts);
  3380.   memcpy(newPoly->norms,polygon->norms,sizeof(pfVec3) * newPoly->numVerts);
  3381.  
  3382.   newPoly->next = gstate->lineList;
  3383.  
  3384.   /* update the head of list pointer */
  3385.   gstate->lineList = newPoly;
  3386.  
  3387.   /* if more than 255 verts create a new holder for the extra verts */
  3388.   if (polygon->numVerts > 255)
  3389.   {
  3390.     newPoly = pfCalloc(1,sizeof(myLines),NULL);
  3391.     newPoly->numVerts = polygon->numVerts - 255;
  3392.     newPoly->cbind = polygon->cbind;
  3393.  
  3394.     /* copy the remaininf polygons values */
  3395.     memcpy(newPoly->coords,polygon->coords[254],sizeof(pfVec3)*
  3396.            newPoly->numVerts);
  3397.  
  3398.     if (polygon->cbind == PFGS_PER_PRIM) 
  3399.     memcpy(newPoly->colors,polygon->colors,sizeof(pfVec4)*
  3400.            newPoly->numVerts);
  3401.     else
  3402.       memcpy(newPoly->colors,polygon->colors[254],sizeof(pfVec4)*
  3403.              newPoly->numVerts);
  3404.     memcpy(newPoly->norms,polygon->norms[254],sizeof(pfVec3) * 
  3405.            newPoly->numVerts);
  3406.  
  3407.     newPoly->next = gstate->lineList;
  3408.     gstate->lineList = newPoly;
  3409.   }
  3410.  
  3411.   /* if the drawstyle is a closed wire then add in the first point again */
  3412.   if (drawStyle == DS_CLOSED_WIRE)
  3413.   {
  3414.     memcpy(newPoly->coords[newPoly->numVerts],
  3415.            polygon->coords[0],sizeof(pfVec3));
  3416.     newPoly->numVerts++;
  3417.   }
  3418.  
  3419. }
  3420.  
  3421. /*========================================================================
  3422.  * Process the gstate list and build gsets for all gstates with polygons
  3423.  * or lines. Also takes into account whether the faces are decals,billboards,
  3424.  * or normal. Finally all gsets are added to the current parent node as 
  3425.  *
  3426.  *========================================================================*/
  3427.  
  3428. static void insertFaces(pfNode *parent,int faceType)
  3429. {
  3430. int         gset;
  3431. pfGeode     *geode;
  3432. pfList      *gsetList;
  3433. dwbGeoState *gstate;
  3434.  
  3435.   /* create the parent geode */
  3436.   geode  = pfNewGeode(); 
  3437.  
  3438.   for (gstate = dwbRoot->gsList; gstate; gstate = gstate->next)
  3439.   {
  3440.     /*----------------------------------------------*/
  3441.     /* convert face set into geosets and add each   */
  3442.     /* one  to the geode. The act of creating the   */
  3443.     /* geosets would reset this geostate builder    */
  3444.     /*----------------------------------------------*/
  3445.     if ( gstate->builder )
  3446.     {
  3447.       gsetList = (pfList *) pfdBuildGSets(gstate->builder); 
  3448.       if (pfGetNum(gsetList) > 0)
  3449.       {
  3450.         for (gset = 0; gset < pfGetNum(gsetList); gset++)
  3451.         {
  3452.           pfGeoSet *geoset = (pfGeoSet*)pfGet(gsetList, gset);
  3453.           /*------------------------------------------*/
  3454.           /* apply current geostate to this geoset.       */
  3455.           /*------------------------------------------*/
  3456.           pfGSetGState(geoset, gstate->pfgs );
  3457.           pfAddGSet(geode, geoset);
  3458.         }
  3459.       }
  3460.     }
  3461.     /* now render any lines */
  3462.     if (gstate->lineList)
  3463.            addLineList(geode,gstate);
  3464.   }
  3465.  
  3466.   if (pfGetNumGSets(geode) == 0) {
  3467.       pfDelete(geode);
  3468.   }
  3469.   else {
  3470.     switch( faceType ) {
  3471.       case BILLBOARD:
  3472.     pfAddChild(parent,(pfNode *) getBillboard(geode));
  3473.       break;
  3474.  
  3475.       /* 
  3476.        * Since pfLayerBase() and pfLayerDecal() are just convenience
  3477.        * routines, we can use pfAddChild() instead, without any problems.
  3478.        */
  3479.  
  3480.       case NORMAL: 
  3481.       case SEQUENCE:
  3482.       case LAYER_DECAL:    /* These two are only for the older version */
  3483.       case LAYER_BASE:     /* and when the renderGrp flag is set       */
  3484.     pfAddChild(parent,(pfNode *) geode);
  3485.       break;
  3486.  
  3487.       default:
  3488.         printf("\nLoadDwb: Internal Error: faceType incorrect\n");
  3489.       break;
  3490.     }
  3491.   }
  3492. }
  3493.  
  3494.  
  3495.  
  3496.  
  3497.  
  3498. printBindType(int bindType)
  3499. {
  3500.   switch (bindType) {
  3501.       case PFGS_PER_VERTEX: 
  3502.                 printf(" PFGS_PER_VERTEX ");
  3503.                 break;
  3504.       case PFGS_PER_PRIM: 
  3505.                 printf(" PFGS_PER_PRIM ");
  3506.                 break;
  3507.       case PFGS_OFF: 
  3508.                 printf(" PFGS_OFF ");
  3509.                 break;
  3510.   }
  3511. }
  3512.  
  3513. printPolygonContents(pfdGeom *poly)
  3514. {
  3515. int loop;
  3516.  
  3517.   printf("Polygon Contents\n");
  3518.   printf("----------------------\n");
  3519.  
  3520.   printf("cbind : ");
  3521.   printBindType(poly->cbind);
  3522.   printf("\n");
  3523.  
  3524.   printf("nbind : ");
  3525.   printBindType(poly->nbind);
  3526.   printf("\n");
  3527.  
  3528.   printf("tbind : ");
  3529.   printBindType(poly->tbind);
  3530.   printf("\n");
  3531.  
  3532.   printf("%d polygons \n",poly->numVerts);
  3533.  
  3534.   for (loop=0; loop < poly->numVerts; loop++)
  3535.     printf("%.2f, %.2f, %.2f\t: %.2f %.2f %.2f \t: %.2f %.2f %.2f\n",
  3536.       poly->coords[loop][0],poly->coords[loop][1],poly->coords[loop][2]
  3537.      ,poly->colors[loop][0],poly->colors[loop][1],poly->colors[loop][2],
  3538.       poly->norms[loop][0],poly->norms[loop][1], poly->norms[loop][2]);
  3539. }
  3540.  
  3541.  
  3542.  
  3543.  
  3544.  
  3545.  
  3546.  
  3547.  
  3548. /*========================================================================
  3549.  * Add a decal layer onto the current parent position
  3550.  * and then stores the children faces after that 
  3551.  * Used only by older versions. [v2.1]
  3552.  *======================================================================== */
  3553. static void handleDecal( pfNode **parent )
  3554. {
  3555.     pfLayer     *layer;
  3556.  
  3557.     /*--------------------------------------------------*/
  3558.     /* construct layer Node & geometry nodes to store   */
  3559.     /* base & decal geom.                               */
  3560.     /*--------------------------------------------------*/
  3561.     layer       = pfNewLayer();
  3562.  
  3563.     pfAddChild(*parent, (pfNode *) layer);
  3564.  
  3565.     insertFaces((pfNode *) layer,LAYER_BASE); 
  3566.  
  3567.     /* create a temporary NEW parent for this group */
  3568.     /* this parent will be retained until the next  */
  3569.     /* pop from the current tree level is received  */
  3570.     /* ie until the end of the group */
  3571.  
  3572.     *parent = (pfNode *)layer;
  3573. }
  3574.  
  3575.  
  3576. /*========================================================================
  3577.  *
  3578.  * FUNCTION    : addLineList
  3579.  * IN          : ptr to current geode & start of a gstate line list.
  3580.  * OUT         : nothing
  3581.  * DESCRIPTION  : create a non-indexed geoset for lines. 
  3582.  *          NB. THIS IS A BAD IMPLEMENTATION...
  3583.  *              I am creating many non-indexed geosets. One for each
  3584.  *              poly-line in this geostate.
  3585.  *
  3586.  *========================================================================*/
  3587.  
  3588.  
  3589. static void addLineList ( pfGeode *geode,dwbGeoState *gstate )
  3590. {
  3591.     pfGeoSet     *pfgs;
  3592.     myLines      *pptr = gstate->lineList;
  3593.     int          i,j,k,nverts = 0,nlines = 0;
  3594.     pfVec3       *n3, *v3;
  3595.     pfVec4       *c4;
  3596.  
  3597.     pfgs = pfNewGSet(Arena);
  3598.  
  3599.     nlines = 0;
  3600.     nverts = 0;
  3601.  
  3602.     while ( pptr )
  3603.     {
  3604.         nlines += pptr->numVerts -1;
  3605.         nverts += pptr->numVerts;
  3606.         pptr = pptr->next; 
  3607.     }
  3608.  
  3609.  
  3610.     if (nlines == 0)
  3611.       return;
  3612.  
  3613.     pfGSetPrimType ( pfgs, PFGS_LINES );
  3614.         
  3615.     pfGSetNumPrims ( pfgs,nlines ); 
  3616.     pfGSetAttr(pfgs, PFGS_TEXCOORD2, PFGS_OFF, NULL, NULL);
  3617.     pfGSetAttr(pfgs, PFGS_NORMAL3, PFGS_OFF, NULL, NULL);
  3618.     pfGSetAttr(pfgs, PFGS_COLOR4, PFGS_OFF, NULL, NULL);
  3619.  
  3620.     if ( gstate->values.binding )
  3621.     {
  3622.         v3 = (pfVec3*) pfMalloc( sizeof(pfVec3)*nlines * 2,Arena);
  3623.         n3 = (pfVec3*) pfMalloc( sizeof(pfVec3)*nlines * 2,Arena);
  3624.         c4 = (pfVec4*) pfMalloc( sizeof(pfVec4)*nlines * 2,Arena);
  3625.  
  3626.     pptr = gstate->lineList;
  3627.     j = k = 0;
  3628.         while ( pptr )
  3629.         {
  3630.             for ( i=1; i < pptr->numVerts; i++)
  3631.             {
  3632.             PFCOPY_VEC3(v3[j], pptr->coords[i-1]);
  3633.             PFCOPY_VEC3(n3[j], pptr->norms[i-1] );
  3634.             if ( gstate->lineList->cbind == PFGS_PER_VERTEX )
  3635.                 PFCOPY_VEC4(c4[j], pptr->colors[i-1] );
  3636.             j++;
  3637.  
  3638.             PFCOPY_VEC3(v3[j], pptr->coords[i]);
  3639.             PFCOPY_VEC3(n3[j], pptr->norms[i] );
  3640.             if ( gstate->lineList->cbind == PFGS_PER_VERTEX )
  3641.                 PFCOPY_VEC4(c4[j], pptr->colors[i-1] );
  3642.             j++;
  3643.  
  3644.                 if ( gstate->lineList->cbind == PFGS_PER_PRIM )
  3645.                 PFCOPY_VEC4(c4[k], pptr->colors[0] );
  3646.             k ++;
  3647.             }
  3648.         
  3649.             pptr = pptr->next; 
  3650.         }
  3651.  
  3652.         pfGSetAttr(pfgs, PFGS_COORD3,PFGS_PER_VERTEX, v3, NULL);
  3653.     pfGSetAttr(pfgs, PFGS_NORMAL3,PFGS_PER_VERTEX, n3, NULL);
  3654.     if ( gstate->lineList->cbind == PFGS_PER_VERTEX )
  3655.         pfGSetAttr(pfgs, PFGS_COLOR4,PFGS_PER_VERTEX, c4, NULL);
  3656.     else if ( gstate->lineList->cbind == PFGS_PER_PRIM )
  3657.         pfGSetAttr(pfgs, PFGS_COLOR4,PFGS_PER_PRIM, c4, NULL);
  3658.     }
  3659.     else
  3660.     {
  3661.         v3 = (pfVec3*) pfMalloc( sizeof(pfVec3)*nlines*2,Arena);
  3662.         c4 = (pfVec4*) pfMalloc( sizeof(pfVec4)*nlines*2,Arena);
  3663.  
  3664.     pptr = gstate->lineList;
  3665.     j = k = 0;
  3666.         while ( pptr )
  3667.         {
  3668.             for ( i = 1; i <=(pptr->numVerts -1); i++)
  3669.             {
  3670.             PFCOPY_VEC3(v3[j], pptr->coords[i-1]);
  3671.             if ( gstate->lineList->cbind == PFGS_PER_VERTEX )
  3672.                 PFCOPY_VEC4(c4[j], pptr->colors[i-1] );
  3673.             j++;
  3674.  
  3675.             PFCOPY_VEC3(v3[j], pptr->coords[i]);
  3676.             if ( gstate->lineList->cbind == PFGS_PER_VERTEX )
  3677.                 PFCOPY_VEC4(c4[j], pptr->colors[i] );
  3678.             j++;
  3679.  
  3680.                 if ( gstate->lineList->cbind == PFGS_PER_PRIM )
  3681.                 PFCOPY_VEC4(c4[k], pptr->colors[0] );
  3682.             k ++;
  3683.         }
  3684.  
  3685.             pptr = pptr->next; 
  3686.         }
  3687.         
  3688.         pfGSetAttr(pfgs, PFGS_COORD3,PFGS_PER_VERTEX, v3, NULL);
  3689.     if ( gstate->lineList->cbind == PFGS_PER_VERTEX )
  3690.         pfGSetAttr(pfgs, PFGS_COLOR4,PFGS_PER_VERTEX, c4, NULL);
  3691.     else
  3692.         pfGSetAttr(pfgs, PFGS_COLOR4,PFGS_PER_PRIM, c4, NULL);
  3693.     }
  3694.         
  3695.     /*----------------------------------------------*/
  3696.     /* apply current geostate to this geoset.        */
  3697.     /*----------------------------------------------*/
  3698.     pfGSetGState ( pfgs, gstate->pfgs ); 
  3699.     pfAddGSet ( geode, pfgs );
  3700.     
  3701.     freeLineList ( gstate );
  3702.     
  3703. }
  3704.  
  3705.  
  3706.  
  3707.  
  3708.  
  3709.  
  3710.  
  3711. static void freeLineList ( dwbGeoState *gstate )
  3712. {
  3713.     myLines *p,*pnext;
  3714.  
  3715.     p = gstate->lineList;
  3716.     while (p)
  3717.     {
  3718.         pnext = p->next;
  3719.         pfFree(p);
  3720.         p = pnext;
  3721.     }
  3722.     gstate->lineList = NULL;
  3723. }
  3724.  
  3725. /* ==========================================================================
  3726.  * Set up performer structure that corresponds with the dwb lightpoint
  3727.  * definition
  3728.  * ========================================================================== */
  3729.  
  3730. static int handleLightPoint(memPtr *ifp, pfdGeom *polygon,pfNode **parent, 
  3731.                 pfNode *current, int vertType)
  3732. {
  3733. dwbLightPt lpnt;
  3734. pfGeode *geode;
  3735. pfGeoSet *gset;
  3736. pfGeoState *gstate;
  3737. pfLPointState *lpState;
  3738. pfVec3 *vertices;
  3739. pfVec4 *colors;
  3740. pfVec3 *normal;
  3741. short opcode,length;  
  3742. int loop;
  3743.  
  3744.   memRead(&lpnt,sizeof(dwbLightPt),1,ifp);
  3745.   USERFUNCS(DB_LIGHT_PT, &lpnt, NULL, *parent,ifp);
  3746.  
  3747.   geode = pfNewGeode ();
  3748.   gset = pfNewGSet (Arena);
  3749.   pfAddGSet (geode, gset);
  3750.  
  3751.   gstate = pfNewGState (Arena);
  3752.   lpState = pfNewLPState (Arena);
  3753.  
  3754.   pfGStateMode (gstate, PFSTATE_ENLPOINTSTATE, 1);
  3755.   pfGStateAttr (gstate, PFSTATE_LPOINTSTATE, lpState);
  3756.  
  3757.   pfGStateMode (gstate, PFSTATE_ENLIGHTING, 0);
  3758.   pfGStateMode (gstate, PFSTATE_ENFOG, 0); 
  3759.   pfGStateMode (gstate, PFSTATE_TRANSPARENCY, PFTR_BLEND_ALPHA);
  3760.   pfGStateVal (gstate, PFSTATE_ALPHAREF, 1.0f/255.0f);
  3761.   pfGStateMode (gstate, PFSTATE_ALPHAFUNC, PFAF_GREATER);
  3762.   pfGStateMode (gstate, PFSTATE_ENTEXTURE, 0);
  3763.  
  3764.   /*
  3765.    * I should be using the 'pntsize' field from the previous face record.
  3766.    * Right now just give it some defaults.
  3767.    * Also some of the other Performer 2.0 stuff is not yet supported in 
  3768.    * DWB 3.0. So just give it some defaults.
  3769.    */
  3770.  
  3771.   pfLPStateMode (lpState, PFLPS_SIZE_MODE, PFLPS_SIZE_MODE_ON);
  3772.   pfLPStateVal (lpState, PFLPS_SIZE_ACTUAL, lpnt.diam);
  3773.  
  3774.   pfLPStateVal (lpState, PFLPS_SIZE_MIN_PIXEL, 0.25f);
  3775.   pfLPStateVal (lpState, PFLPS_SIZE_MAX_PIXEL, 4.0f);
  3776.  
  3777.   pfLPStateVal (lpState, PFLPS_TRANSP_PIXEL_SIZE, 2.0f);
  3778.   pfLPStateVal (lpState, PFLPS_TRANSP_EXPONENT, 1.0f);
  3779.   pfLPStateVal (lpState, PFLPS_TRANSP_SCALE, 0.6f);
  3780.   pfLPStateVal (lpState, PFLPS_TRANSP_CLAMP, 0.1f); 
  3781.  
  3782.   pfLPStateVal (lpState, PFLPS_FOG_SCALE, 0.25f); 
  3783.  
  3784.   pfLPStateMode (lpState, PFLPS_RANGE_MODE, PFLPS_RANGE_MODE_TRUE);
  3785.  
  3786.   switch (lpnt.directionality)
  3787.   {
  3788.     case DB_OMNIDIRECTIONAL:
  3789.       pfLPStateMode (lpState, PFLPS_DIR_MODE, PFLPS_DIR_MODE_OFF);
  3790.     break;
  3791.  
  3792.     case DB_UNIDIRECTIONAL:
  3793.       pfLPStateMode (lpState, PFLPS_SHAPE_MODE, PFLPS_SHAPE_MODE_UNI);
  3794.       pfLPStateMode (lpState, PFLPS_DIR_MODE, PFLPS_DIR_MODE_ON);
  3795.     break;
  3796.  
  3797.     case DB_BIDIRECTIONAL:
  3798.       if (faceBackColor >= 0)
  3799.       {
  3800.       pfVec4 color;
  3801.  
  3802.         pfLPStateMode (lpState, PFLPS_SHAPE_MODE, PFLPS_SHAPE_MODE_BI_COLOR);
  3803.         pfCopyVec3 (color, dwbRoot->colorTable[faceBackColor]);
  3804.         color[3] = dwbRoot->currentGroup.alpha;    
  3805.     pfLPStateBackColor (lpState, color[0], color[1], color[2], color[3]);
  3806.       }
  3807.       else pfLPStateMode (lpState, PFLPS_SHAPE_MODE, PFLPS_SHAPE_MODE_BI);
  3808.       pfLPStateMode (lpState, PFLPS_DIR_MODE, PFLPS_DIR_MODE_ON);
  3809.     break;
  3810.  
  3811.     default:
  3812.       printf("LoadDwb: Error - unknown lightpoint type\n");
  3813.       return(0);
  3814.   }
  3815.  
  3816.   pfLPStateShape (lpState, lpnt.lwidth, lpnt.lheight, 0.0f, 1.0f, 0.1f);
  3817.   pfAddChild (*parent, geode);
  3818.  
  3819.  
  3820.   /*
  3821.    * Configure the geoset with PFGS_POINTS primitive type and PFGS_OVERALL
  3822.    * normal binding. Once DWB supports per-lightpoint-normal, I should
  3823.    * change this. Similarly, the face level color is used for all the light
  3824.    * points
  3825.    */
  3826.  
  3827.   vertices = pfCalloc (sizeof (pfVec3), polygon->numVerts, Arena);
  3828.   normal = pfCalloc (sizeof (pfVec3), 1, Arena);
  3829.   colors = pfCalloc (sizeof (pfVec4), polygon->numVerts, Arena);
  3830.  
  3831.   pfGSetPrimType (gset, PFGS_POINTS);
  3832.   pfGSetGState (gset, gstate);
  3833.   pfGSetNumPrims (gset, polygon->numVerts);
  3834.  
  3835.   /* 
  3836.    * now read in the vertex record associated with this light string 
  3837.    */
  3838.  
  3839.   memRead(&opcode,sizeof(short),1,ifp);
  3840.   if (opcode != DB_PUSH)
  3841.   {
  3842.     printf("LoadDwb:Error - file format incorrect \n");
  3843.     return (0);
  3844.   }
  3845.   else dwbPush(parent,current);
  3846.  
  3847.   memRead(&length,sizeof(short),1,ifp);
  3848.   memSeek(ifp,length,SEEK_CUR);
  3849.  
  3850.   /* next record MUSt be a vertex record */
  3851.   memRead(&opcode,sizeof(short),1,ifp);
  3852.   if (opcode != DB_VERTEX)
  3853.   {
  3854.     printf("LoadDwb:Error - file format incorrect \n");
  3855.     return (0);
  3856.   }
  3857.  
  3858.   /* read the vertices into polygon */
  3859.   memRead (&length,sizeof(short),1,ifp);
  3860.   handleVertex (ifp, vertType, polygon, length);
  3861.  
  3862.   /* add the points to the light points node */
  3863.   for (loop=0; loop < polygon->numVerts; loop++)
  3864.   {
  3865.     PFCOPY_VEC3 (vertices[loop], polygon->coords[loop]);
  3866.     PFCOPY_VEC3 (colors[loop], polygon->colors[0]);
  3867.     colors[loop][3] = dwbRoot->currentGroup.alpha;
  3868.   }
  3869.   PFCOPY_VEC3 (normal[0], lpnt.dir);
  3870.  
  3871.   pfGSetAttr (gset, PFGS_NORMAL3, PFGS_OVERALL, (void *) normal, NULL);
  3872.   pfGSetAttr (gset, PFGS_COORD3, PFGS_PER_VERTEX, (void *) vertices, NULL);
  3873.   pfGSetAttr (gset, PFGS_COLOR4, PFGS_PER_VERTEX, (void *) colors, NULL);
  3874.  
  3875.   return(1);
  3876. }
  3877.  
  3878.  
  3879.  
  3880. /* ==========================================================================
  3881.  * draw callback for a bspline group. Just calls gl routine
  3882.  * ========================================================================== */
  3883.  
  3884. static int drawBspline ( pfTraverser *trav, void *data )
  3885. {
  3886. BsplineInfo *bsp = (BsplineInfo *) data;
  3887.   pfPushState();
  3888.   pfDisable(PFEN_TEXTURE);
  3889.   pfDisable(PFEN_LIGHTING);
  3890.  
  3891. #ifdef IRISGL
  3892.   c4f(bsp->color);
  3893.   nurbscurve(bsp->numKnots, bsp->knots, 3*sizeof(double),bsp->cntlPnts,4,N_V3D);
  3894. #else
  3895.   glColor4f (bsp->color[0], bsp->color[1], bsp->color[2], bsp->color[3]);
  3896.   gluBeginCurve (bsp->nobj);
  3897.     gluNurbsCurve (
  3898.       bsp->nobj, 
  3899.       (GLint) bsp->numKnots, bsp->knots, 
  3900.       3, bsp->cntlPnts, 
  3901.       4, GL_MAP1_VERTEX_3
  3902.     );
  3903.  
  3904.   gluEndCurve (bsp->nobj);
  3905. #endif /* end GL type */
  3906.   pfPopState();
  3907. }
  3908.  
  3909.  
  3910.  
  3911. static int clipRegionOn ( pfTraverser *trav, void *data )
  3912. {
  3913. ClipRegion *clip = (ClipRegion *) data;
  3914.  
  3915. #ifdef IRISGL
  3916.   if (clip->gotOld) 
  3917.     scrmask(clip->min[0], clip->max[0], clip->min[1], clip->max[1]); 
  3918. #else
  3919.   if (clip->gotOld)
  3920.   {
  3921.     glEnable (GL_SCISSOR_TEST);
  3922.     glScissor (clip->min[0], clip->min[1], 
  3923.            clip->max[0] - clip->min[0] - 1, 
  3924.            clip->max[1] - clip->min[1] - 1);
  3925.   }
  3926. #endif /* end GL type */
  3927. }
  3928.  
  3929.  
  3930.  
  3931. static int clipRegionOff ( pfTraverser *trav, void *data )
  3932. {
  3933. ClipRegion *clip = (ClipRegion *) data;
  3934.  
  3935. #ifdef IRISGL
  3936. Matrix projection_matrix;
  3937. #else
  3938. GLfloat projection_matrix[4][4];
  3939. #endif /* end GL type */
  3940.  
  3941. static int countdown = 3; /* nothing may be drawn for first three frames */
  3942.  
  3943.    if (!countdown)
  3944.    {
  3945. #ifdef IRISGL
  3946.    mmode (MPROJECTION);
  3947.    getmatrix (projection_matrix);
  3948.    mmode(MVIEWING);
  3949. #else
  3950.    glMatrixMode (GL_PROJECTION);
  3951.    glGetFloatv (GL_PROJECTION_MATRIX, (GLfloat *) projection_matrix);
  3952.    glMatrixMode (GL_MODELVIEW);
  3953. #endif /* end GL type */
  3954.  
  3955.     if (clip->gotOld || clipMode == CLIP_RECALCULATE )
  3956.     {
  3957. #ifdef IRISGL
  3958.       if (!clip->gotOld) 
  3959.         getscrmask(&clip->oldmin[0], &clip->oldmax[0],
  3960.                    &clip->oldmin[1], &clip->oldmax[1]);
  3961. #else
  3962.       if (!clip->gotOld)
  3963.       {
  3964.       GLint temp[4];
  3965.  
  3966.     glGetIntegerv (GL_SCISSOR_BOX, temp);
  3967.     clip->oldmin[0] = temp[0];
  3968.     clip->oldmin[1] = temp[1];
  3969.     clip->oldmax[0] = temp[0]+temp[2]-1;
  3970.     clip->oldmax[1] = temp[1]+temp[3]-1;
  3971.       }
  3972. #endif /* end GL type */
  3973.  
  3974.       if (clip->oldmin[0] == 0 && clip->oldmax[0] ==0 
  3975.           && clip->oldmin[1] == 0 && clip->oldmax[1] ==0)
  3976.       {
  3977.         printf("Error: zero scrmask \n");
  3978.     clip->oldmin[0] =0;
  3979.     clip->oldmax[0] =1280;
  3980.     clip->oldmin[1] =0;
  3981.     clip->oldmax[1] =1024;
  3982.       }
  3983.     
  3984.  
  3985.  
  3986.       clip->channel = pfGetTravChan(trav);
  3987.       pfGetChanSize(clip->channel,&clip->chanSize[0],&clip->chanSize[1]);
  3988.       pfGetChanOrigin(clip->channel,&clip->chanOrigin[0],&clip->chanOrigin[1]);
  3989.  
  3990.       map_viewport (clip,clip->channel,clip->ll,clip->ur,clip->min,clip->max);
  3991.  
  3992.       clip->gotOld = 1; 
  3993.     }
  3994. #ifdef IRISGL
  3995.     scrmask( clip->oldmin[0], clip->oldmax[0], clip->oldmin[1], clip->oldmax[1]);
  3996. #else
  3997.     glEnable (GL_SCISSOR_BOX);
  3998.     glScissor (clip->oldmin[0], clip->oldmin[1], 
  3999.            clip->oldmax[0] - clip->oldmin[0]-1, 
  4000.            clip->oldmax[1] - clip->oldmin[1]-1);
  4001. #endif /* end GL type */
  4002.   }
  4003.   else
  4004.     countdown --;
  4005.  
  4006. }
  4007.  
  4008.  
  4009.  
  4010.  
  4011. /* ==========================================================================
  4012.  * Performer callback to ensure that a node with no geometry is switched on
  4013.  * ========================================================================== */
  4014. int switchOn(pfTraverser *trav, void *data)
  4015. {
  4016.   return PFTRAV_CONT;
  4017. }
  4018.  
  4019.  
  4020.  
  4021.  
  4022.  
  4023.  
  4024. /* ==========================================================================
  4025.  * Take a group thats a bspline and set up the appropriate callback so that
  4026.  * it gets rendered correctly
  4027.  * ========================================================================== */
  4028.  
  4029. static int handleBSpline(memPtr *ifp, short length, pfNode *current, 
  4030.                          pfNode *parent)
  4031. {
  4032. dwbBSpline bspline;
  4033. double *knots,*cntlPnts;
  4034. pfVec3 *points;
  4035. short opcode;
  4036. BsplineInfo *bsp;
  4037. pfGroup *grp;
  4038. pfSphere sphere;
  4039. int i, numPoints;
  4040.  
  4041.   /* read the bspline record*/
  4042.   memRead(&bspline,length,1,ifp);
  4043.  
  4044.   /* read the next record which should be a knots record */
  4045.   memRead(&opcode,sizeof(short),1,ifp);
  4046.   memRead(&length,sizeof(short),1,ifp);
  4047.  
  4048.   if (opcode != DB_BSPLINE_KNOTS )
  4049.   {
  4050.     memSeek(ifp,-4,SEEK_CUR);
  4051.     printf("Error: bspline record not followed by knots record \n");
  4052.     return(0);
  4053.   }
  4054.  
  4055.   knots = pfMalloc(length,Arena);
  4056.   memRead(knots,length,1,ifp);
  4057.  
  4058.   /* now read the control points */
  4059.   memRead(&opcode,sizeof(short),1,ifp);
  4060.   memRead(&length,sizeof(short),1,ifp);
  4061.  
  4062.   if (opcode != DB_BSPLINE_CNTRL_PNTS)
  4063.   {
  4064.     memSeek(ifp,-4,SEEK_CUR);
  4065.     printf("Error: bspline record not followed by control points record \n");
  4066.     return(0);
  4067.   }
  4068.  
  4069.  
  4070.   cntlPnts = pfMalloc(length,Arena);
  4071.   memRead(cntlPnts,length,1,ifp);
  4072.  
  4073.   /* now do something with the blighters */
  4074.   bsp = pfMalloc(sizeof(BsplineInfo),Arena);
  4075.  
  4076.   /* setup a pfVec3 array for calculating the bounding sphere */
  4077.   numPoints = length/sizeof(double)/3;
  4078.   points = (pfVec3 *) pfMalloc (sizeof (pfVec3)*numPoints, Arena);
  4079.   for (i=0; i<length/sizeof(double); ++i) {
  4080.     points[i/3][i%3] = (float) cntlPnts[i];
  4081.   } 
  4082.  
  4083.   bsp->numKnots = bspline.numKnots;
  4084.  
  4085. #ifdef IRISGL
  4086.   bsp->knots = knots;
  4087.   bsp->cntlPnts = cntlPnts;
  4088. #else
  4089.   bsp->knots = pfCalloc (bsp->numKnots, sizeof (GLfloat), Arena);
  4090.   bsp->cntlPnts = pfCalloc (numPoints*3, sizeof (GLfloat), Arena);
  4091.   for (i=0; i<bsp->numKnots; ++i) bsp->knots[i] = (GLfloat) knots[i];
  4092.   for (i=0; i<numPoints*3; ++i) bsp->cntlPnts[i] = (GLfloat) cntlPnts[i];
  4093.   pfFree (knots);
  4094.   pfFree (cntlPnts);
  4095.   bsp->nobj = gluNewNurbsRenderer ();
  4096. #endif /* end GL type */
  4097.  
  4098.   pfCopyVec4(bsp->color,nextBSplineColor);
  4099.  
  4100.   /* make a new node */
  4101.   grp = pfNewGroup();
  4102.   pfAddChild(parent,grp);
  4103.  
  4104.   USERFUNCS (DB_BSPLINE, &bspline, (pfNode *)grp, parent,ifp);
  4105.   USERFUNCS (DB_BSPLINE_KNOTS, &knots, (pfNode *)grp, parent,ifp);
  4106.   USERFUNCS (DB_BSPLINE_CNTRL_PNTS, &cntlPnts, (pfNode *)grp, parent,ifp);
  4107.  
  4108.   pfNodeTravFuncs(grp,PFTRAV_CULL,switchOn, NULL); 
  4109.   pfNodeTravFuncs(grp, PFTRAV_DRAW,drawBspline,NULL);
  4110.   pfNodeTravData(grp, PFTRAV_DRAW, (void *) bsp);
  4111.  
  4112.   /* ----------------------------------------- */
  4113.   /* Create a culling sphere around the group  */
  4114.   /* ----------------------------------------- */
  4115.  
  4116.   pfSphereAroundPts (&sphere, points, numPoints);
  4117.   pfNodeBSphere(grp, &sphere, PFBOUND_STATIC);
  4118.   pfFree (points);
  4119.  
  4120.   return (1);
  4121. }
  4122.  
  4123.  
  4124. static int handleArc (memPtr *ifp, short length,pfNode *current,
  4125.                     pfNode *parent)
  4126. {
  4127.     dwbArc arc;
  4128.     ArcInfo *arcinfo;
  4129.     pfGroup *group;
  4130.  
  4131.   memRead (&arc, length, 1, ifp);
  4132.   arcinfo = pfMalloc (sizeof(ArcInfo), Arena);
  4133.  
  4134.   pfCopyMat (arcinfo->matrix, arc.matrix);
  4135.   pfCopyVec3 (arcinfo->pfNormal, arc.pfNormal);
  4136.   arcinfo->drawstyle = arc.drawstyle;
  4137.   arcinfo->fRadius = arc.fRadius;
  4138.   arcinfo->fStartAngle = arc.fStartAngle;
  4139.   arcinfo->fEndAngle = arc.fEndAngle;
  4140.  
  4141.   {                                
  4142.       float tmp_arr[4]; int tmp_int;                
  4143.     if ( arc.color == PACKED_COLOR_INDEX )            
  4144.     {                                
  4145.         unPackRGBA ( arc.packed_color,tmp_arr );            
  4146.         for ( tmp_int=0; tmp_int<3; tmp_int++ )            
  4147.             arcinfo->color[tmp_int] = tmp_arr[tmp_int]; 
  4148.     }                            
  4149.     else                            
  4150.     pfCopyVec3 ( arcinfo->color,dwbRoot->colorTable[arc.color] );
  4151.     arcinfo->color[3] = dwbRoot->currentGroup.alpha;        
  4152.   }
  4153.  
  4154.   group = pfNewGroup ();
  4155.   pfAddChild (parent, group);
  4156.  
  4157.   USERFUNCS (DB_ARC, &arc, (pfNode *) group, parent, ifp);
  4158.  
  4159.   pfNodeTravFuncs (group, PFTRAV_CULL, switchOn, NULL);
  4160.   pfNodeTravFuncs (group, PFTRAV_DRAW, drawArc, NULL);
  4161.   pfNodeTravData (group, PFTRAV_DRAW, (void *) arcinfo);
  4162.  
  4163.   pfNodeBSphere (group, &groupBoundingSphere, PFBOUND_STATIC);
  4164.  
  4165.   return 1;
  4166. }
  4167.  
  4168.  
  4169. static int drawArc ( pfTraverser *trav, void *data ) 
  4170. {
  4171.     ArcInfo *arcinfo = (ArcInfo *) data;
  4172.  
  4173.   pfPushState();
  4174.   pfDisable (PFEN_TEXTURE);
  4175.   pfDisable (PFEN_LIGHTING);
  4176.   pfPushMatrix();
  4177.  
  4178. #ifdef IRISGL
  4179.   mmode(MVIEWING);
  4180. #else
  4181.   glMatrixMode (GL_MODELVIEW);
  4182. #endif /* end GL type */
  4183.  
  4184.   pfMultMatrix(arcinfo->matrix);
  4185.  
  4186. #ifdef IRISGL
  4187.   c4f (arcinfo->color);
  4188.   n3f (arcinfo->pfNormal);
  4189.   if (arcinfo->drawstyle == DS_SOLID || 
  4190.       arcinfo->drawstyle == DS_SOLID_BOTH_SIDES) {
  4191.     arcf (0, 0, arcinfo->fRadius, arcinfo->fStartAngle*10, 
  4192.         arcinfo->fEndAngle*10);
  4193.   }
  4194.   else {
  4195.     arc (0, 0, arcinfo->fRadius, arcinfo->fStartAngle*10, 
  4196.            arcinfo->fEndAngle*10);
  4197.   }
  4198. #else
  4199.   /* XXX need to do the right thing here */
  4200. #endif /* end GL type */
  4201.     
  4202.   pfPopMatrix();
  4203.   pfPopState();
  4204. }
  4205.  
  4206. /* ==========================================================================
  4207.  * Convert a geode into a pfBillboard and return a pointer to that billboard.
  4208.  * The current implementation of Performer 1.2 has a number of problems
  4209.  * with Billboards. These are
  4210.  
  4211.     1) Only geometry that is XZ planar will be drawn. Anything else
  4212.        is rotated incorrectly. For our case this also means that
  4213.        the geometry MUST be defined Z-up. Any attempt I make to correct
  4214.        foils the performer pfBillboard logic.
  4215.  
  4216.     2) Contrary to the manual, _all_ primitives of a geoset are rotated
  4217.        independently, and again only faces that are planar in XZ will
  4218.        be displayed. Effectively, this means that a billboard needs to
  4219.        be a single face in the XZ plane.
  4220.  *
  4221.  *
  4222.  * ========================================================================= */
  4223.  
  4224. static pfBillboard *getBillboard(pfGeode *geode)
  4225. {
  4226. int gset;
  4227. pfBox box1,box2,*box,*bigBox;
  4228. int nbox;
  4229. pfVec3 pnt;
  4230. pfSCS *scs;
  4231. pfMatrix mat;
  4232. pfBillboard *bill;
  4233.  
  4234.   /* ------------------------------------ */ 
  4235.   /* First find centre point of the geode */
  4236.   /* ------------------------------------ */ 
  4237.   nbox = pfGetNumGSets(geode);
  4238.  
  4239.   /* use pointers to the structures to simplify the next bit */
  4240.   box = &box1;
  4241.   bigBox = &box2;
  4242.  
  4243.   for (gset = 0; gset < nbox; gset++)
  4244.   {
  4245.     pfGeoSet *geoset = (pfGeoSet*)pfGetGSet(geode, gset);
  4246.     /*-------------------------*/
  4247.     /* Calculate bounding box  */
  4248.     /*-------------------------*/
  4249.     pfGSetBBox(geoset, NULL, PFBOUND_DYNAMIC);
  4250.     pfGetGSetBBox(geoset,box);
  4251.     if (gset == 0)
  4252.         memcpy(bigBox,box,sizeof(pfBox));
  4253.     else     
  4254.         PFBOX_EXTENDBY_BOX(bigBox, box);
  4255.   }
  4256.  
  4257.   /* ---------------------------------------------------------- */
  4258.   /* now that we have the overall bounding box - get the centre */
  4259.   /* ---------------------------------------------------------- */
  4260.   pnt[0] = (bigBox->min[0] + (bigBox->max[0] - bigBox->min[0])/2.0f);
  4261.   pnt[1] = (bigBox->min[1] + (bigBox->max[1] - bigBox->min[1])/2.0f);
  4262.   pnt[2] = (bigBox->min[2] + (bigBox->max[2] - bigBox->min[2])/2.0f);
  4263.  
  4264.   /* --------------------------------------------------------------- */
  4265.   /* translate the geometry so that it will rotate around its origin */
  4266.   /* --------------------------------------------------------------- */
  4267.  
  4268.   pfMakeTransMat(mat,-pnt[0],-pnt[1],-pnt[2]);
  4269.   scs = pfNewSCS(mat);
  4270.   pfAddChild(scs,geode);
  4271.   pfFlatten(scs,0);
  4272.  
  4273.   /* ----------------------------------------------------------- */
  4274.   /* need to extract the gsets from the geode and attach them to */
  4275.   /* our billboard and set the position of each geoset.          */
  4276.   /* ----------------------------------------------------------- */
  4277.  
  4278.   bill = pfNewBboard();
  4279.  
  4280.   for (gset = 0; gset < nbox; gset++)
  4281.   {
  4282.     pfGeoSet *geoset = (pfGeoSet*)pfGetGSet(geode, gset);
  4283.  
  4284.     pfAddGSet(bill, geoset);
  4285.     pfRemoveGSet(geode, geoset);
  4286.     pfBboardPos(  bill,gset, pnt);       
  4287.   }
  4288.  
  4289.   return(bill);
  4290. }
  4291.  
  4292.  
  4293.  
  4294.  
  4295.  
  4296. getOrientation( void )
  4297. {
  4298.   if ( dwbRoot->header.up_axis == Y_UP )
  4299.     return(1);
  4300.   else
  4301.     return(0);
  4302.  
  4303. }
  4304.  
  4305.  
  4306.  
  4307. convertOrigin( float val[3] )
  4308. {
  4309. float buff[3];
  4310.  
  4311.   copyNyup(buff,val,dwbRoot->unitChange)
  4312.   memcpy(val,buff,sizeof(float) *3 );
  4313. }
  4314.  
  4315.  
  4316. float getUnitChange( void )
  4317. {
  4318.   return (dwbRoot->unitChange);
  4319. }
  4320.  
  4321.  
  4322. void getCpackColor( int index, float *cols )
  4323. {
  4324.   pfCopyVec3(cols, dwbRoot->colorTable[index]);
  4325. }
  4326.  
  4327.  
  4328.  
  4329. /* ------------------------------------------------------------------------- */
  4330. /*                     User Callback Processing                              */
  4331. /* ------------------------------------------------------------------------- */
  4332.  
  4333.  
  4334. /*
  4335.  * set all user callbacks to the standard value -  but just the once
  4336.  */
  4337.  
  4338. int initUserFuncs(void)
  4339. {
  4340. int loop;
  4341. static int alreadyCalled = 0;
  4342.  
  4343.   if (alreadyCalled)
  4344.     return 0;
  4345.   else
  4346.     alreadyCalled = 1;
  4347.  
  4348.   for (loop=0;loop< DB_LASTREC - DB_HEADER; loop++)
  4349.     userFunctions[loop].func = NULL;
  4350.   return 1;
  4351. }
  4352.  
  4353.  
  4354.  
  4355.  
  4356.  
  4357. /* 
  4358.  * Set a user defined callback into the callback table
  4359.  * return -1 on failure, 1 on success
  4360.  */
  4361.  
  4362. int setUserFuncs(int type, int (func)(int type, void *rec, 
  4363.                  pfNode *current, pfNode *parent, memPtr *ifp))
  4364. {
  4365. static int triedToInit=0;
  4366.  
  4367.   if (!triedToInit)
  4368.   {
  4369.     initUserFuncs();
  4370.     triedToInit = 1;
  4371.   }
  4372.  
  4373.   if (type > DB_LASTREC || type < DB_HEADER)
  4374.   {
  4375.     printf("Opcode %d is outside of valid range (%d - %d) \n",type,
  4376.            DB_HEADER,DB_LASTREC);
  4377.     return(-1);
  4378.   }
  4379.  
  4380.   userFunctions[type - DB_HEADER].func = func;
  4381.   return(1);
  4382. }
  4383.  
  4384.  
  4385. int memEof( memPtr *ptr)
  4386. {
  4387.   if (ptr->pos >= ptr->length)
  4388.     return (1);
  4389.   else
  4390.     return(0);
  4391. }
  4392.  
  4393. static void addToFilePath(char *str)
  4394. {
  4395. const char *existing;
  4396. char *new;
  4397. int length;
  4398.  
  4399.   existing = pfGetFilePath();
  4400.   if (! existing) length = strlen(str);
  4401.   else length = strlen (str) + strlen (existing);
  4402.  
  4403.   new = pfCalloc( 1,length + 4,NULL);
  4404.   if (existing) strcat (new, existing);
  4405.   strcat (new, str);
  4406.   pfFilePath(new);
  4407. }
  4408.  
  4409. /*========================================================================
  4410.  *
  4411.  * Try and find the file given by looking in the standard places,
  4412.  * following CS_PATH, and finally PF_PATH
  4413.  * If the file is found then return a pointer to the memPtr otherwise
  4414.  * return NULL
  4415.  *
  4416.  *======================================================================== */
  4417.  
  4418. static memPtr *openFile (char *fileName)
  4419. {
  4420. static char csPath[PF_MAXSTRING] =  "/usr/cs/dwb2/MODELS/MODELS:" 
  4421.                     "/usr/cs/dwb2/MODELS/INST:";
  4422. #undef memPtr
  4423. char path[PF_MAXSTRING];
  4424. FILE *ifp;
  4425. int count;
  4426. static int firstTime = 1;
  4427.  
  4428.   if (firstTime)
  4429.   {
  4430.     /* append the CS_PATH environment variable */
  4431.     if (getenv("CS_PATH"))
  4432.       strncat(csPath,getenv("CS_PATH"), PF_MAXSTRING - strlen (csPath));
  4433.  
  4434.     /* set the search path */
  4435.     addToFilePath(csPath);
  4436.     firstTime = 0;
  4437.   }
  4438.  
  4439.   /*------------------------------------------*/
  4440.   /* find the file...                         */
  4441.   /*------------------------------------------*/
  4442.   if (!pfFindFile(fileName, path, R_OK))
  4443.   {
  4444.     /* this is causing an intermitent core dump */
  4445.     /* commenting out seems to solve the problem */
  4446.  
  4447.     pfNotify(PFNFY_WARN,PFNFY_RESOURCE,
  4448.             "LoadDwb: Could not find \"%s\" in\n  %s\n", fileName,
  4449.         pfGetFilePath ());
  4450.  
  4451.     return (NULL);
  4452.   }
  4453.  
  4454.   if (pfGetNotifyLevel() >= PFNFY_NOTICE)
  4455.       pfNotify(PFNFY_NOTICE,PFNFY_RESOURCE, "Loading file %s\n", path);
  4456.  
  4457.   /*------------------------------------------*/
  4458.   /* try and open it                          */
  4459.   /*------------------------------------------*/
  4460.   if ( (ifp = fopen(path, "rb")) == NULL )
  4461.   {
  4462.       pfNotify(PFNFY_WARN,PFNFY_RESOURCE,
  4463.               "LoadDwb: Could not access \"%s\"", path);
  4464.       return (NULL);
  4465.   }
  4466.  
  4467.   /* ok its a file - prepare to load it -init "all" the global variables */
  4468.   initLoader();
  4469.  
  4470.   /* get the file length */
  4471.   fseek(ifp,0,SEEK_END);
  4472.   dwbRoot->file.length = ftell(ifp);
  4473.  
  4474.   if (dwbRoot->file.length == 0) 
  4475.   {
  4476.     pfNotify (PFNFY_WARN, PFNFY_RESOURCE,
  4477.           "LoadDwb: File \"%s\" is empty\n", path);
  4478.     return (NULL);
  4479.   }
  4480.  
  4481.   /* create the temporary buffer */
  4482.   dwbRoot->file.ptr = pfMalloc(dwbRoot->file.length,NULL);
  4483.  
  4484.   /* reset the file ptr */
  4485.   fseek(ifp,0,SEEK_SET);
  4486.  
  4487.   /* read everything into memory */
  4488.   count = fread(dwbRoot->file.ptr,1,dwbRoot->file.length,ifp);
  4489.  
  4490.   if (count != dwbRoot->file.length)
  4491.   {
  4492.     perror("Error Reading file into memory buffer");
  4493.     return(NULL);
  4494.   }
  4495.  
  4496.   fclose(ifp);
  4497.  
  4498.   /* initialise the "file" pointer */
  4499.   dwbRoot->file.pos = 0;
  4500.  
  4501.   return (&dwbRoot->file);
  4502.  
  4503. }
  4504.  
  4505.  
  4506.  
  4507.  
  4508.  
  4509.  
  4510.  
  4511.  
  4512.  
  4513. #ifdef IRISGL
  4514. int wtoscrn (Matrix the_matrix, float world_pt [3], short screen_pt [2])
  4515. #else
  4516. int wtoscrn (GLfloat the_matrix[4][4], float world_pt [3], short screen_pt [2])
  4517. #endif /* end GL type */
  4518. {
  4519.     float xnew, ynew, znew, wnew,wid,hgt;
  4520.     short x1, x2, y1, y2;
  4521.  
  4522.     xnew = world_pt [0] * the_matrix [0][0] + world_pt [1] *
  4523.       the_matrix [1][0] + world_pt [2] * the_matrix [2][0] + the_matrix [3][0];
  4524.  
  4525.    ynew = world_pt [0] * the_matrix [0][1] + world_pt [1] *
  4526.      the_matrix [1][1] + world_pt [2] * the_matrix [2][1] + the_matrix [3][1];
  4527.  
  4528.     znew = world_pt [0] * the_matrix [0][2] + world_pt [1] *
  4529.       the_matrix [1][2] + world_pt [2] * the_matrix [2][2] + the_matrix [3][2];
  4530.  
  4531.     wnew = world_pt [0] * the_matrix [0][3] + world_pt [1] *
  4532.       the_matrix [1][3] + world_pt [2] * the_matrix [2][3] + the_matrix [3][3];
  4533.  
  4534.     xnew = xnew / wnew;        /* wnew is an identity that you need */
  4535.     ynew = ynew / wnew;
  4536.  
  4537.  
  4538.     /*------------------------------------------------------------------*/
  4539.     /* if the screen coord needs to be actual physical screen values    */
  4540.     /* as opposed to Window relative then add in the origin factor..    */
  4541.     /*------------------------------------------------------------------*/
  4542.  
  4543. #ifdef IRISGL
  4544.     getviewport (&x1, &x2, &y1, &y2);
  4545. #else
  4546.     {
  4547.     GLint tmp[4];
  4548.  
  4549.       glGetIntegerv (GL_VIEWPORT, tmp);
  4550.       x1 = tmp[0];
  4551.       x2 = tmp[0] + tmp[2]-1;
  4552.       y1 = tmp[1];
  4553.       y2 = tmp[1] + tmp[3]-1;
  4554.     }
  4555. #endif /* end GL type */
  4556.  
  4557.     wid = (float)(x2 - x1);
  4558.     hgt = (float)(y2 - y1);
  4559.  
  4560.     screen_pt [0] = (int)((xnew+1)/2 * wid + (float)x1);
  4561.     screen_pt [1] = (int)((ynew+1)/2 * hgt + (float)y1);
  4562. }
  4563.  
  4564.  
  4565.  
  4566. /*==============================================================*
  4567.  
  4568.    Routine      : (void) map_viewport
  4569.    Purpose      : Maps groups world ll & ur coords into screen
  4570.                   values for use as either a viewport or scrnmask.
  4571.    Parameter(s) : (IP) group_ptr - ptr to group whose viewport is
  4572.                        being defined
  4573.                   (IP) width - width of viewport, in pixels
  4574.                   (IP) height - height of viewport, in pixels
  4575.    Returns      : Nothing (void)
  4576.    Description  :
  4577.  
  4578.  *==============================================================*/
  4579.  
  4580. int map_viewport (ClipRegion *clip,pfChannel *chan, float ll[3],float ur[3], short vw_ll[3],short vw_ur[3])
  4581. {
  4582.    int tmp;
  4583.  
  4584. #ifdef IRISGL
  4585.    Matrix curr_matrix, view_matrix, projection_matrix;
  4586. #else
  4587.    GLfloat curr_matrix[4][4], view_matrix[4][4], projection_matrix[4][4];
  4588. #endif /* end GL type */
  4589.  
  4590.    pfMatrix mat,mat2;
  4591.    short left, right, bottom, top;
  4592.    int width,height;
  4593.    pfCoord coords;
  4594.    pfVec3 dst;
  4595.    pfMatrix modelPos;
  4596.  
  4597.    /* Determine the current matrix */
  4598. #ifdef IRISGL
  4599.    mmode (MPROJECTION);
  4600.    getmatrix (projection_matrix);
  4601.    mmode(MVIEWING);
  4602. #else
  4603.    glMatrixMode (GL_PROJECTION);
  4604.    glGetFloatv (GL_PROJECTION_MATRIX, (GLfloat *) projection_matrix);
  4605.    glMatrixMode (GL_MODELVIEW);
  4606. #endif /* end GL type */
  4607.  
  4608.    pfCopyMat(mat,projection_matrix);
  4609.  
  4610.    /* view matrix contains the 90x rot + channel matrix + channel offset */
  4611. #ifdef IRISGL
  4612.    getmatrix (view_matrix);
  4613. #else
  4614.    glGetFloatv (GL_MODELVIEW_MATRIX, (GLfloat *) view_matrix);
  4615. #endif /* end GL type */
  4616.  
  4617.    pfPreMultMat(mat,view_matrix);
  4618.  
  4619.    pfXformPt3(dst,ll,mat);
  4620.    wtoscrn (mat, ll, vw_ll);
  4621.  
  4622.    pfXformPt3(dst,ur,mat);
  4623.    wtoscrn (mat, ur, vw_ur);
  4624.  
  4625.    if (vw_ll [0] > vw_ur [0])
  4626.    {
  4627.       tmp = vw_ll [0];
  4628.       vw_ll [0] = vw_ur [0];
  4629.       vw_ur [0] = tmp;
  4630.    }
  4631.  
  4632.    if (vw_ll [1] > vw_ur [1])
  4633.    {
  4634.       tmp = vw_ll [1];
  4635.       vw_ll [1] = vw_ur [1];
  4636.       vw_ur [1] = tmp;
  4637.    }
  4638.  
  4639. }
  4640.  
  4641.  
  4642.  
  4643. #ifdef IRISGL
  4644. int printMatrix ( Matrix mat )
  4645. #else
  4646. int printMatrix (GLfloat mat[4][4])
  4647. #endif /* end GL type */
  4648. {
  4649.     register int i,j;
  4650.  
  4651.     printf("\n");
  4652.     printf("MATRIX ...\n" );
  4653.  
  4654.     for (i=0; i<4; i++)
  4655.     {
  4656.         for (j=0; j<4; j++)
  4657.             printf("%f ",mat[i][j] );
  4658.         printf ("\n");
  4659.     }
  4660. }
  4661.  
  4662.  
  4663. setClipMode(int mode)
  4664. {
  4665.   clipMode = mode;
  4666. }
  4667.